...

View Full Version : Please explain the output of this simple C code



abduraooft
07-14-2009, 01:45 PM
The following program gives me 100 and 99.

#include <stdio.h>

void print(int *p,int *q){
printf("%d \n %d",*p,*q);
}
void main(){
static int arr[]={97,98,99,100,101,102,103};
static int *ptr=arr+1;
print(++ptr,++ptr);
}
Please explain me how that 99 comes there.

Thanks

ralph l mayo
07-14-2009, 03:12 PM
Pure luck. The behavior of that code is unspecified.

http://www.experts-exchange.com/Programming/Editors_IDEs/C_CPP_CS/Visual_CPP/Q_23975343.html (http://74.125.95.132/search?q=cache:1C0hXVe34JgJ:www.experts-exchange.com/Programming/Editors_IDEs/C_CPP_CS/Visual_CPP/Q_23975343.html&cd=1&hl=en&ct=clnk&gl=us&client=opera)

tomws
07-14-2009, 03:39 PM
And so for this specific implementation, it looks like it's stacking the pointer location and then rolling back as the printf is evaluated. Is that an accurate observation (again, for this implementation)?

abduraooft
07-14-2009, 03:39 PM
Thanks for that link (which gives many other related links)
But, Isn't
int i=0;
CPrint(++i,++i); equivalent to

int i=0;
i++;i++;
CPrint(i,i);?
ie, evaluate the arguments first(in whatever order it likes) and then call the function?
Or is it calling the function twice(some how by the internal implementation) for passing the arguments one by one?

Is this behaviour exists only in C and C++?

ralph l mayo
07-14-2009, 04:58 PM
The unspecified order of argument evaluation is only on facet of the problem with that line of code. The expanded second version *does* have defined behavior, because it introduces sequence points (http://en.wikipedia.org/wiki/Sequence_point) between the increment ops.

Even if the language guaranteed left-to-right evaluation of function arguments, since side-effects of ++ are not resolved until the next sequence point, there are still (at least) two possibilities:


// compiler fully-evaluates arguments as soon as possible
CPrint(++i, ++i) == /* pseudocode */ args[0] = ++i; args[1] = ++i; CPrint(args[0], args[1])
// if i is 2, cprint is passed 3, 4

// compiler decides to "optimize" by defering incrementing
// the variable until just before the sequence point
CPrint(++i, ++i) == /* pseudocode */ CPrint(i + 1, i + 1); i += 2;
// if i is 2, cprint is passed 3, 3


Once the sequence point is hit i is always going to hold a predictable value, but before then if you write twice to the same variable there's no guarantee that either have happened yet.

edit:
oops, the second pseudo-code is misleading because there is a sequence point before the function is entered. What it's really doing is setting both args to i + 1, incrementing i by 2, and *then* calling the function. The difference isn't really consequential because the function doesn't have a pointer to i anyway.

oracleguy
07-14-2009, 05:02 PM
You could also have your compiler generate the listing file for that code and you could see how it went about implementing it in assembly. Might be kind of interesting.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum