Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I don't understand what is passed to the function f() when I call it like this.

main()
{
  void f(int,int);
  int i=10;
  f(i,i++);
}

void f(int i,int j)
{ printf("%d %d",i,j); }

gives me 11 10 .Can somebody explain why its 11?

share|improve this question
7  
Try it and find out :) –  Mason Wheeler May 28 '12 at 18:02
    
I did that, but I need an explanation –  nischayn22 May 28 '12 at 18:02
2  
@nischayn22: Can you post the results and explaint he part you don't understand? Also, have you tried f(i,++i); and compared it to f(i,i++);? –  FrustratedWithFormsDesigner May 28 '12 at 18:03
1  
@FrustratedWithFormsDesigner I did that, it gives me 11 11 in first case and 11 10 in second..But I don't get why the first parameter is 11 –  nischayn22 May 28 '12 at 18:11
    
Eu! Why would you feel compelled to write this sort of thing? –  ncmathsadist May 29 '12 at 1:55

3 Answers 3

up vote 4 down vote accepted

The behavior is undefined, as follows:

From the C99 standard:

6.5 Expressions
...
2 Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.72) Furthermore, the prior value shall be read only to determine the value to be stored.73)
72) A floating-point status flag is not an object and can be set more than once within an expression.
73) This paragraph renders undefined statement expressions such as

    i = ++i + 1;
    a[i++] = i;
while allowing

    i = i + 1;
    a[i] = i;

We're violating the second sentence of that paragraph; we're not just reading the prior value to determine the new value to be stored.

Note that undefined doesn't necessarily mean illegal. Undefined simply means that the compiler is free to handle the situation any way it sees fit; any result is considered "correct". You could very well wind up with the result you expected. Or not. The program could crash. Or not. Or anything else could happen.

In this case, you will get different results based on platform, compiler, optimization settings, surrounding code, etc. The reason for that is as follows:

6.5.2.2 Function calls
...
10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

It is unspecified whether i or i++ is evaluated first; furthermore, it is unspecified whether the side effect of ++ is applied immediately after i++ is evaluated, as follows:

6.5.2.4 Postfix increment and decrement operators
...
2 The result of the postfix ++ operator is the value of the operand. After the result is obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate type is added to it.) See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The side effect of updating the stored value of the operand shall occur between the previous and the next sequence point.

Emphasis mine.

Edit

Changed the wording a bit to make it clear that the behavior is undefined.

share|improve this answer
    
Your middle paragraph says unspecified, but your first says undefined. Which is it? –  Pubby May 29 '12 at 10:02
    
Since the order of evaluations and side effects are unspecified, you will get different results under different circumstances. The behavior is left undefined so that compilers aren't required to do anything in particular when they encounter code like that. This case would be easy enough to detect and issue a diagnostic against, but what about a case like f(*a, (*b)++); where both a and b are set to point to i? In a different translation unit? –  John Bode May 29 '12 at 11:06
    
@Pubby Both. If a variable gets a value stored anywhere in an expression, one is not allowed to read the same variable elsewhere in that same expression for any other purposes than to determine the value to store. Since the OP's code did this, it is invoking undefined behavior (meaning anything can happen). But on top of that, the order of evaluation of function parameters is unspecified behavior, meaning that the order of the evaluation will be either left-side or right-side first and the compiler does not need to document or tell us which one that applies. –  user29079 Jun 1 '12 at 13:37

Because undefined behaviour, that's why. You read the value twice and modify it once with no intervening sequence point, which is a giant pile of illegal. Even if it were not illegal, the compiler has no obligation to evaluate your function arguments in any particular order, or indeed, to even evaluate one fully before evaluating another.

share|improve this answer
    
Is this really UB? I thought it was only UB if it was modified twice without a sequence point. (either way you can't rely on the output) –  Pubby May 28 '12 at 18:16
1  
It's the order of operations that is undefined. The compiler can choose to evaluate i either before or after i++. –  Steven Burnap May 28 '12 at 20:25
    
@Pubby: today (C++11) it's called sequenced-before/sequenced-after. The evaluation of the first argument is sequenced neither or after the second. The result is still the same here: UB. –  MSalters May 28 '12 at 21:13
2  
@Steven: That would be unspecified, not undefined. In particular, it means that foo(bar(), baz()); is perfectly well defined, but may call either bar or baz first. –  MSalters May 28 '12 at 21:15
    
Sorry, yeah, you're right. –  Steven Burnap May 28 '12 at 21:25

The order of evaluation of function arguments is unspecified and so 11 10 is a correct possible output.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.