Interview question !!!

P

prashna

void fn (void);

main ()
{
int i = 20;
fn ();

printf ("%d\n",i);
}

void fn (void)
{
// add ur code only here so that i in main should print OTHER THAN 20
}
Is there any Legal solution for this?
Thanks,
Ashwath
 
N

Noah Roberts

prashna said:
void fn (void);

main ()
{
int i = 20;
fn ();

printf ("%d\n",i);
}

void fn (void)
{
// add ur code only here so that i in main should print OTHER THAN 20
}
Is there any Legal solution for this?

As far as I know nothing portable. However, you could probably
overwrite the stack. i will probably be on the stack right before the
return location. You would be invoking undefined behaviour.

Maybe something like this:

void fn(void)
{
int x;
*(&x - 2) = 5;
}

I have no idea if 2 is right or if you don't need to add instead. A
decent programmer would not do such a thing. Unless you are in a very
specialty field you probably don't want to work for the person who
created this question.
 
J

James Hu

void fn (void);

main ()
{
int i = 20;
fn ();

printf ("%d\n",i);
}

void fn (void)
{
// add ur code only here so that i in main should print OTHER THAN 20
}
Is there any Legal solution for this?
Thanks,
Ashwath

Sure:

void fn (void)
{
puts("OTHER THAN 20");
exit(0);
}

-- James
 
R

Roose

Try declaring a stack variable in fn(), taking its address, and backtracking
on the stack and modifying i. That is, get a new pointer by
adding/subtracting. How far to backtrack depends on the implementation.
With a debugger that can view memory, this should be easy to figure out.

It is "legal" in the sense that it's well-formed C, but it's not portable.
 
J

Jack Klein

in comp.lang.c:

Please don't top post, it is against usenet guidelines and makes
technical discussions extremely hard to read. Thanks.
Try declaring a stack variable in fn(), taking its address, and backtracking
on the stack and modifying i. That is, get a new pointer by
adding/subtracting. How far to backtrack depends on the implementation.
With a debugger that can view memory, this should be easy to figure out.

What's a "stack variable"? On several compilers I use, there is no
such thing.
It is "legal" in the sense that it's well-formed C, but it's not portable.

The standard does not define either "legal" or "well-formed". The C++
standard defines the term "ill-formed", but that group's down the hall
on the left.

If by "legal" you mean that all compilers must compile it, then you're
quite wrong. Since the program invokes undefined behavior, the
standard specifically allows compilers to reject it at compile time.
 
R

Roose

Please don't top post, it is against usenet guidelines and makes
technical discussions extremely hard to read. Thanks.

I'm going to ignore this. Go to the other thread to talk about this.
What's a "stack variable"? On several compilers I use, there is no
such thing.

Some variables are stored on the stack, with "auto" storage. This is in
contrast to those that are statically or dynamically allocated. If you
can't understand this, then I doubt you actually code in the real world and
work successfully with others.

Let me guess. You also boil with rage over HTML e-mail, Microsoft software,
and people who don't format code like yourself. I wonder how any of you get
things done -- oh wait, you don't. You're probably underemployed -- sadly
with some decent skills/knowledge -- and sit at home fiddling with your
operating system all day, while people without such brittle personalities
build interesting things that people use.
If by "legal" you mean that all compilers must compile it, then you're
quite wrong. Since the program invokes undefined behavior, the
standard specifically allows compilers to reject it at compile time.

I'll grant you that. But I don't care, because I care about getting things
done, and answering questions. Not trivial technicalities. Show me a
compiler and platform with a stack where this technique does not work. Then
we'll talk.

And why don't you be constructive, and show me another way to answer the
original poster's question.
 
M

Martin Ambuhl

Roose said:
I'm going to ignore this. Go to the other thread to talk about this.

Ignoring constructive and correct advise is a sign of an antisocial misfit,
someone of whom it could be said
> I doubt you actually code in the real world and
> work successfully with others.

Some variables are stored on the stack, with "auto" storage. This is in
contrast to those that are statically or dynamically allocated. If you
can't understand this, then I doubt you actually code in the real world and
work successfully with others.

That you don't understand that automatic variables need not have anything
to do with a stack suggests that you don't
> actually code in the real world and that you can't
> work successfully with others.
And why don't you be constructive, and show me another way to answer the
original poster's question.

The correct answer was: "There is no legal way to do this; any claim other
wise is bullshit from someone who doesn't
 
C

Chris Torek

... Show me a compiler and platform with a stack where this
technique [i.e., taking the address of a local automatic-storage
variable, pretending it is a pointer to an array of such variables,
and indexing out of bounds in that nonexistent array]
does not work. Then we'll talk.

Try it on a Pyramid; you may be surprised.

(The Pyramids has TWO stacks, and it is difficult to predict which
stack an automatic variable will be on. So, even if you somehow
"know" the distance between stack frames, you may not find the
other variable(s) you expect.)
And why don't you be constructive, and show me another way to answer the
original poster's question.

There *are* no good answers to the OP's question (which seems to
have disappeared -- what happened to useful context? -- but which
I recall as being something like this):

"You are given a function f() that has an automatic variable x.
If f() calls g(), but does not pass g() the address of x, and
does not take the address of x anywhere, and does not store a
return value from g() into x, how can you reliably modify x
from within g()?"

The answer is: you cannot. Compilers move variables around all the
time. A compiler that sees that f() never modifies x after it is
assigned an initial value may actually *remove* x, replacing all
later references to x with the value that was stored earlier.

In short, the OP wants a good way to shoot himself in the foot;
and the replies have pointed out that shooting yourself in the foot
is a bad idea. And indeed, it *is* a bad idea -- the compiler may
not be using a .22, but a .45, and the hydrostatic shock could kill
you.
 
R

Roose

I can easily dispatch this with cut and paste: Show me a compiler and
platform with a stack where this technique does not work. Then we'll talk.

Martin Ambuhl said:
Ignoring constructive and correct advise is a sign of an antisocial misfit,
someone of whom it could be said

Don't get in a pissing contest with me. Without knowing anything about you,
I can say with reasonable certainty that my code has been used by more
people than yours, and it could very well be in your house now, if you own a
game console. Of course I could be wrong, as I said, but judging by your
personality I'll take the leap.
That you don't understand that automatic variables need not have anything
to do with a stack suggests that you don't

This is not real world stuff. You're talking trivialities. I am aware that
auto != stack. A stack is a way to implement the C language idea of auto.
This is the last of your trivialities I care to answer. Your pissing
contests utterly bore me.

If I spoke in rigid, exacting, technically correct language, people would be
overwhelmed by details they don't care about. I choose to speak informally
but meaningfully, which is why I'm employed solving real problems in the
real world.
The correct answer was: "There is no legal way to do this; any claim other
wise is bullshit from someone who doesn't

No. The correct answer is what the interviewer wants to hear. Take a step
back from your insular little world of the C standard as a bible, and look
at the larger problem. Getting a job. In an interview, you would be the
guy that refuses to acknowledge this practical fact, unpure as it may be.
The guy who shows he knows how a stack works will be the one who gets a job.
A perfect example of why my "underemployed" flame was, again, witheringly
accurate.
 
A

Arthur J. O'Dwyer

[interview question with no answer]

Here's a *slightly* more interesting variation, which
(even though it admits of stupid preprocessor tricks)
*still* doesn't have any solution AFAICS. Pedant points
to anyone who *can* find a solution. :)

-Arthur


void fn(void)
{
/* add your code here so that main should print something
* other than 20
*/
}

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}
 
R

Richard Heathfield

Noah said:
Unless you are in a very
specialty field you probably don't want to work for the person who
created this question.

Actually, it would be a very useful question. Someone who can tell you (a)
how to do it on some systems, (b) why it won't work on other systems, and
(c) why you should never, /ever/ do it at all, would score pretty highly in
my book.
 
R

Roose

Thanks for the info, that was useful and interesting. I agree that it's a
terrible idea, and if I saw anyone do that in real code I would be pissed.
However, I'm reading between the lines here, getting into the interviewer's
head, and assuming that he wants the guy to demonstrate that he knows how
99.9% of stacks work, and basic C pointer arithmetic.

Chris Torek said:
... Show me a compiler and platform with a stack where this
technique [i.e., taking the address of a local automatic-storage
variable, pretending it is a pointer to an array of such variables,
and indexing out of bounds in that nonexistent array]
does not work. Then we'll talk.

Try it on a Pyramid; you may be surprised.

(The Pyramids has TWO stacks, and it is difficult to predict which
stack an automatic variable will be on. So, even if you somehow
"know" the distance between stack frames, you may not find the
other variable(s) you expect.)
And why don't you be constructive, and show me another way to answer the
original poster's question.

There *are* no good answers to the OP's question (which seems to
have disappeared -- what happened to useful context? -- but which
I recall as being something like this):

"You are given a function f() that has an automatic variable x.
If f() calls g(), but does not pass g() the address of x, and
does not take the address of x anywhere, and does not store a
return value from g() into x, how can you reliably modify x
from within g()?"

The answer is: you cannot. Compilers move variables around all the
time. A compiler that sees that f() never modifies x after it is
assigned an initial value may actually *remove* x, replacing all
later references to x with the value that was stored earlier.

In short, the OP wants a good way to shoot himself in the foot;
and the replies have pointed out that shooting yourself in the foot
is a bad idea. And indeed, it *is* a bad idea -- the compiler may
not be using a .22, but a .45, and the hydrostatic shock could kill
you.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://67.40.109.61/torek/index.html (for the moment)
Reading email is like searching for food in the garbage, thanks to
spammers.
 
J

James Hu

[interview question with no answer]

Here's a *slightly* more interesting variation, which
(even though it admits of stupid preprocessor tricks)
*still* doesn't have any solution AFAICS. Pedant points
to anyone who *can* find a solution. :)

-Arthur

Still needs:

#include said:
void fn(void)
{
/* add your code here so that main should print something
* other than 20
*/

You could do:

#define printf(a, b) printf("something\n * other than " a, b)

But perhaps:

#define fn() i -= 5

is more what you had in mind?
}

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}


On the original question, does no output count as something
other than 20?

#include <stdio.h>

void fn(void);

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}

void fn(void)
{
fclose(stdout);
}

There is no "valid way" to alter the value of i from within fn() from
the provided prototype. Depending on the platform, there may be a gross
hack, but any such implementation of the hack would depend upon many
assumptions, and the implementation could still sometimes fail. If
altering the value of i is really needed, the address of i should be
communicated to fn() in some way (either as a parameter to the function,
or stored in a variable within both main's and fn's scope).

If this was really an interview question, your answer should be that
as a developer, you would be very uncomfortable delivering any code
that would attempt to perform the action that they are requesting,
since the code would be unreliable. You should then point out all
the problems with any solution that attempts to manipulate i without
passing its address to fn(). Then recommend the software be redesigned,
since modifying i from within fn() is obviously a new requirement, and
necessitates a change to the interface. Ask for the documentation on
fn() so that you can assess it, then generate a proposal for the design
change. Ask your interviewer to sign off on the proposal after the
design review, then implement the design.

-- James
 
J

Jeremy Yallop

Arthur said:
Here's a *slightly* more interesting variation, which
(even though it admits of stupid preprocessor tricks)
*still* doesn't have any solution AFAICS. Pedant points
to anyone who *can* find a solution. :)

-Arthur

#include said:
void fn(void)
{
/* add your code here so that main should print something
* other than 20
*/

#define i i = 10, j
}

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}

Jeremy.
 
C

Christian Bau

"Arthur J. O'Dwyer said:
[interview question with no answer]

Here's a *slightly* more interesting variation, which
(even though it admits of stupid preprocessor tricks)
*still* doesn't have any solution AFAICS. Pedant points
to anyone who *can* find a solution. :)

-Arthur


void fn(void)
{ #define i j=5, k
}

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}

Passing more arguments to printf then handled by the format string is
perfectly legal; all unused arguments are just ignored.
 
T

Tim Woodall

Arthur J. O'Dwyer said:
[interview question with no answer]

Here's a *slightly* more interesting variation, which
(even though it admits of stupid preprocessor tricks)
*still* doesn't have any solution AFAICS. Pedant points
to anyone who *can* find a solution. :)

-Arthur


void fn(void)
{
/* add your code here so that main should print something
* other than 20
*/
}

int main(void)
{
int i = 20;
fn();
printf("%d\n", i);
return 0;
}

printf("2");

Now it will print 220 instead of 20.

Tim.
 
J

Joona I Palaste

Tim Woodall said:
Now it will print 220 instead of 20.

I wish *I* had thought of that. But still, the answer I gave in that
other thread was also a good one, right? Right? RIGHT?
 
A

Alan Balmer

I'm going to ignore this. Go to the other thread to talk about this.

Please don't ignore it, it's good advice.

Also, please include attributions for your quotes.
 
A

Alan Balmer

You're probably underemployed -- sadly
with some decent skills/knowledge -- and sit at home fiddling with your
operating system all day, while people without such brittle personalities
build interesting things that people use.

That's funny! I suggest that you stop fiddling with yourself for a
moment, and do some minimal research - typing "Jack Klein" into Google
would be a good start.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top