The Gateway to Computer Science Excellence
+18 votes
4.1k views

What will be the output of the following code?

#include<stdio.h>
int main()
{
    int x=10, y;
    y = (x++) + (++x);
    printf("%d %d %d %d ", y, x++, x, ++x);
}
  1. 22,10,11,13
  2. 22,11,11,11
  3. 12,10,11,13
  4. 22 13 13 13
in Programming by Veteran | 4.1k views
+3

The undefined thing is - Order  of evaluation of expression .

In which order it will evaluate , that is not defined in C standard.

1 Answer

+39 votes
Best answer

None of the choices is correct as per C standard. This is because the statement

y = (x++) + (++x);

can cause undefined behavior, so does the statement

printf("%d %d %d %d ", y, x++, x, ++x);

C standard says that the side effects of an operation (for ++a; modification of a is a side-effect and return of a+1 is main effect) need to be completed only before the next sequence point. This relaxation is given so that the compiler would be able to generate the most optimal code (which run faster). But as a consequence, programmer shouldn't do a read and a write from a memory location between two consecutive sequence points or otherwise the result would be undefined.

In the statement,

y = (x++) + (++x);

There are 2 reads to the memory location of x and 2 writes to the same between two consecutive sequence points. So, the result of this statement has no guarantee as per C standard.

Similarly, the statement

printf("%d %d %d %d ", y, x++, x, ++x);

is undefined. In a function call in C, the order in which the argument expressions are processed is not defined. The only thing defined is that all arguments must be processed before the next sequence point- which here is the start of execution of the called function.

Undefined value means compiler can give any value. i.e.; different compilers or even different versions of the same compiler can give different answers. As per C standard, no programmer should write this code. This is different from compiler defined, in which case the output is clearly defined by the compiler and programmer can write those code as long as he is aware of the compiler. Example of compiler defined code is sizeof(int).

Still undefined

    #include<stdio.h>
    int main()
    {
    int x=10;
    printf("%d %d %d\n", x++, x, ++x);
    }
[email protected]:~$ gcc undefined.c
[email protected]:~$ ./a.out
11 12 12
[email protected]:~$ icc undefined.c
[email protected]:~$ ./a.out
10 12 12
[email protected]:~$ clang undefined.c
[email protected]:~$ ./a.out
10 11 12

Is this Problem with ++? NO

#include<stdio.h>
int main()
{
    int x=10;
    printf("%d %d %d\n", x=1, x, x=2);
}
    [email protected]:~$ gcc -Wall undefined.c
    undefined.c: In function ‘main’:
    undefined.c:6:35: warning: operation on ‘x’ may be undefined [-Wsequence-point]
    printf("%d %d %d\n", x=1, x, x=2);
    ^
    undefined.c:6:35: warning: operation on ‘x’ may be undefined [-Wsequence-point]
    [email protected]:~$ ./a.out
    1 1 1
    [email protected]:~$ icc -Wall undefined.c
    [email protected]:~$ ./a.out
    1 2 2
    [email protected]:~$ clang -Wall undefined.c
    [email protected]:~$ ./a.out
    1 1 2

Precedence Rule Violated? No

Undefined behaviour is happening not because C is violating precedence rule. Precedence (and associativity which is used when precedence of operators are same) rule is used to specify the operands for operations. But the actual execution order might be different. For example:

x = a*b+c*d;

After applying precedence rule, we get

x = ((a*b) + (c*d));

Thus the first $*$ has operands $a$ and $b$, the second $*$ has operands $c$ and $d$, the $+$ has operands returned by the result of two $*$ and $=$ has left operand $x$ and right operand the result of $+$. But, during execution $(a*b)$ or $(c*d)$ can occur first as both these won't be violating the precedence rule.

Similarly, if we take

y = x++ * ++x;

After applying precedence rule, we get

y = ((x++) * (++x));

$x$++ or ++$x$ can happen first. Suppose ++$x$ happened first. It'll surely return $x+1$. But whether this incremented $x$ is used by $x$++ is not guaranteed. This increment can happen to $x$ ANYTIME before the next sequence point, which here is the ; at the end of the expression. This makes this code produce undefined behaviour.

Other Examples for Undefined behaviour

  1. int i = 2;
  2. i = i++;
  3. printf("%d\n", i);
  4. Possible outputs: $\{3, 2\}$
  1. int i = 2;
  2. a[i] = i++;
  3. Possible Results: $a[2] = 2, a[3] = 2$
  1. int i = 2, j;
  2. j = (i++) * (++i);
  3. printf("%d", j);
  4. Possible outputs: $\{6, 8, 9\}$
  1. int i = 2;
  2. printf("%d %d", i, i++);
  3. Possible outputs: $\{(2,2), (3,2)\}$
by Veteran
selected by
+1
Sir thanks, I too compiled with clang, regarding this type of questions, to see different results.
0
How we could know the sequence point in c ? Suppose we write i=i++ then what is sequence point here .
+3

; is the sequence point.
in i = i++, according to precedence it is i = (i++).
So, i will be incremented, but we don't know if incremented value will be assigned or the old value will be assigned to i. 

+2
Between two sequence point, we should not read and write the same variable. In C the order of any operation between two sequence points is completely up to the compiler. So we don't know whether assignment will happen first or increment will happen first which leads to undefined behavior.
In i = i++ we are assigning i as well as incremented i and reading i from the memory, between two sequence point.
0
a[count++] == ++count;

Sir, this is an undefined behaviour. (Right?)

But what if, count is a global variable. and we do:

a[count++] = incr();

and in another function:

int incr() {
    return ++count;
}

Is it still undefined? Or function call will be executed first?

0

@Rishabh Gupta 2

i hope No, why?

++count is encounters sequence point.

0

Similarly undefined behaviour in Python 

a=256
b=256
a is b
True

a=257
b=257
a is b
False

257 is 257 
True

 

Reason

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object. So it should be possible to change the value of 1. I suspect the behaviour of Python in this case is undefined. :-)

Reference

+1

@Arjun sir, 

In this code, 

int i=2,j;

j= (i++)*(++i); 

printf("%d",j);

I am getting possible output as {6,8,9}. But u said possible output as 6 and 9.

How i am getting 8?

If i++ is executed first, then 2 is returned (main effect) and if the side effect (incrementing i ) before seeing ++i , then i is changed to 3 and on executing ++i , i is incremented to 4 and 4 is returned. Therefore, j= 2*4 = 8.

Is this correct sir?

And in this code,

int i=2;

printf("%d %d", i,i++);

Possible outputs are { (2,2), (3,2) }

Explanation for (3,2) :

If the argument i++ is executed first, then 2 will be returned and if side effect of i++ occurs before the other argument i , then i will return 3. Therefore the statement becomes printf("%d %d", 3,2);  which will print (3,2). 

Sir is this also correct? Sir i am not getting (2,3) as output in this code.

0
Yes, you are correct. I have updated. Thanks.

This is not in GATE syllabus for C but whatever you told is part of "synchronous execution" in Operating Systems for GATE.
0
Ok sir. Thanks.
Answer:

Related questions

Quick search syntax
tags tag:apple
author user:martin
title title:apple
content content:apple
exclude -tag:apple
force match +apple
views views:100
score score:10
answers answers:2
is accepted isaccepted:true
is closed isclosed:true
52,215 questions
59,965 answers
201,156 comments
118,184 users