-2

Could anyone please explain the result of the following C program?

#include<stdio.h>

int main()
{
    int i=2;
    printf("%d %d %d",i,i++,++i);
    return 0;
}

How is the output 4 3 4?

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Companion/cxx_crib/increment.html – Pavel May 12 '14 at 01:13
  • 3
    I can't give you a proper answer about the specific values emitted, but I do know that it's undefined behaviour. The C standard does not dictate the order of evaluation of parameters into a function. – Karl Nicoll May 12 '14 at 01:13
  • Adding to what @KarlNicoll said, the output may differ between compilers. For example I tried with clang and it gave `2 2 4` instead. – Brian Bi May 12 '14 at 01:15
  • 3
    There are several thousand dups of such ridiculous questions about riduculous code. Nobody in their right mind would write such rubbish, and nobody really cares about the results. – Martin James May 12 '14 at 01:18
  • 2
    please read this guideline on sequence points http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points – baci May 12 '14 at 01:20
  • `c++` tag removed, because the question specifically says this is a "C program", and C++'s "happens before" relation is completely irrelevant when using a C compiler. – Ben Voigt May 12 '14 at 01:20
  • @CanberkBaci: That link concerning outdated C++ rules is not very helpful to a question about C. – Ben Voigt May 12 '14 at 01:22
  • @BenVoigt, There's a non-outdated answer below: http://stackoverflow.com/a/4183735/962089. You probably knew that, but it's there at least. – chris May 12 '14 at 02:04
  • @chris: yeah after commenting to you I saw that and commented to the owner of the faq to change the accepted answer. Still not applicable to a C program. – Ben Voigt May 12 '14 at 02:14
  • @BenVoigt, Agreed. A fair number of C++ FAQs are, but this one is not. – chris May 12 '14 at 02:18

3 Answers3

3

The order of evaluation of arguments is undefined by the C++ standard; and also, "if a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined".

Therefore, the post-increment and pre-increment on the same scalar value as arguments to the same function call is undefined. Obviously both increments are being done prior to the first and last arguments being evaluated, in your case.

Andrew McGuinness
  • 2,092
  • 13
  • 18
0

You start with i = 2. Because of i++ and ++i, the variable i is increased by 2 (each ++ adds 1). Therefore, when you are finished, its value is 4.

The syntax i++ says that to use the value if i before incrementing it. That is why the middle number (which printf gets from i++) cannot be 4.

The reason it is 4 3 4 and not something else such as 2 2 4 or 2 3 3 or 4 3 3 has to do with when the ++ operators are evaluated compared to when the parameters of the printf function are set. One should simply never write code like that, at least not for software that anyone actually has to use.

David K
  • 3,147
  • 2
  • 13
  • 19
0

You have entered the land of Undefined Behaviour. C makes no guarantees about the order in which the arguments being passed to a function are evaluated, especially not varargs functions. The outcome of a statement like this, which is a classic interview question, is "unknown" -- it can change between compiler versions, platforms, etc, and is similar to the question:

int i = 1;
int a[3] = { 1, 2, 3 };
int j = a[i++] - a[++i];

What is j? Answer: it depends on your compiler, version, platform, etc: the one thing you cannot use to deduce it is the C specification.

But you're wondering about the 3, aren't you? That's because your compiler evaluated ++i first, which incremented i to 3. Then your compiler evaluated i++, the post increment, which is implemented equivalent to this (in C++, sorry):

int operator ++ (int) { // post-increment indicated by int parameter
    int i = *this;
    this->operator++();
    return i;
}

or in other pseudo code

int tempI = i;
++i;

so what you actually wrote was:

printf("%d %d %d\n", i, (j = i, ++i), ++i);

at the end of evaluating the arguments to pass to printf, i had the value 4, but the temporary returned by i++ retained its value of 3.

Hence: 4(i) 3(temp) 4(i)

kfsone
  • 23,617
  • 2
  • 42
  • 74