-3

So I am stuck with this question.

int i=5,a;
a=++i + i++ + ++i + i++ - --i;
printf("%d",a);

According to me 'a' should be 20. a=6+6+8-8 However, on execution I found the answer to be 18. What I am doing wrong? A step by step explanation would be helpful.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
  • please post your thoughts first - then we can correct you – Jan Dragsbaek Oct 03 '11 at 18:56
  • 8
    Again such a question about abuse of operators. This must be just one instructor out there who always asks the same question? (please search for "sequence point" in C). – Jens Gustedt Oct 03 '11 at 18:58
  • Why it's so undefined? It's pretty calculable if pay attention to operator's precedence. And it merely evaluates to 18: 1) i can't change its value within expression 2) ++i have higher precendence then i++ (which will be applied after statement is evaluated). 6 + 5 + 6 + 5 - 4 = 18 – Vladimir Fesko Oct 03 '11 at 19:13
  • "so undefined", never seen that one :) (operator precedence only says how the expression is interpreted and not in which order subexpressions are to be evaluated.) – Jens Gustedt Oct 03 '11 at 20:18

5 Answers5

3

This is undefined behavior. A variable cannot be changed more than once between sequence points. Your program can output anything. Any answer stating otherwise is wrong.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
3

I have written about this in a detailed manner in my blog post at: http://blog.susam.in/2010/05/sequence-points.html

I am posting some extracts from it here.

A particular type of question is asked time after time in C programming forums. There are two things about such questions that irritate the experienced programmers in the forums. Firstly, this type of questions is so common that many don't even want to respond to them even if it means posting a link to another thread where a similar question has been answered. Secondly, and more importantly, even if someone tries to provide the correct answer to the question, there are many others who ignore it and fill up the thread with incorrect answers.

The questions usually involve finding the output of a code like this.

#include <stdio.h>

int main()
{
    int i = 5;
    printf("%d %d %d\n", i, i--, ++i);
    return 0;
}

The output is 5 6 5 when compiled with gcc and 6 6 6 when compiled with Microsoft C/C++ compiler that comes with Microsoft Visual Studio.

The behaviour of such C programs is undefined. In the statements printf("%d %d %d\n", i, i--, ++i); and a += a++ + a++;, semicolon is the only sequence point. C guarantees that all side effects of a given expression is completed by the next sequence point in the program. If two or more operations with side effects affecting each other occur before the next sequence point, the behavior is undefined. Such code may behave differently when compiled with different compilers.

Before I quote the relevant sections from the ISO/IEC standard, let me quote something from K&R. In Section 2.12 (Precedence and Order of Evaluation) of the book, the authors write,

C, like most languages, does not specify the order in which the

operands of an operator are evaluated. (The exceptions are &&, ||, ?:, and ','.) For example, in a statement like

x = f() + g();

f may be evaluated before g or vice versa; thus if either f or g

alters a variable on which the other depends, x can depend on the order of evaluation. Intermediate results can be stored in temporary variables to ensure a particular sequence.

They provide one more example in this section.

One unhappy situation is typified by the statement

a[i] = i++;

The question is whether the subscript is the old value of i or the

new. Compilers can interpret this in different ways, and generate different answers depending on their interpretation.

If you want to read more on this, download the ISO/IEC 9899 C standard and turn to page 438 for Annex C – Sequence Points. It lists down all the sequence points. ; is one of them. + and ++ operators are not sequence points.

Next, read section 5.1.2.3 (Program execution), point 2.

Accessing a volatile object, modifying an object, modifying a

file, or calling a function that does any of those operations are all side effects,11) which are changes in the state of the execution environment. Evaluation of an expression may produce side effects. At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place. (A summary of the sequence points is given in annex C.)

Susam Pal
  • 32,765
  • 12
  • 81
  • 103
1

In the standard for C, it says explicitly that a compiler is free to rearrange the expression in any way so long as the precedence rules are followed. This means that if you have this expression:

x = foo() + bar() + baz()

The three functions could be called in any order and it is legal.

In older standards for C, it even said that a compiler could ignore parentheses if it wanted to:

x = (foo() + bar()) + baz()

The only sure way to force a certain order of evaluation is to use temporary variables:

temp0 = foo();
temp1 = bar();
x = temp0 + temp1 + baz();
steveha
  • 74,789
  • 21
  • 92
  • 117
0

The expression you are assigning to a exhibits undefined behavior, specifically the order in which the increment/decrement operations are applied to their operands.

David R Tribble
  • 11,918
  • 5
  • 42
  • 52
0

Depends on which order the compiler does everything in. Since it's compiler-implementation dependent, there's no "right" answer.

E.g. going strictly left->right:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     first   second  third  fourth  fifth
a = (6) + (6) + (8) + (8) - (7) = 21;

going right->left:

a = (++i) + (i++) + (++i) + (i++) - (--i);
     fifth   fourth third   second    first
a =  6 + 5 + 5 + 4 - 4 = 16;
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • It's even less deterministic than that - you can get different results for the same compiler, depending on optimization settings, surrounding code, etc. – John Bode Oct 03 '11 at 19:15
  • Indeed. I just went for the easiest two examples. – Marc B Oct 03 '11 at 19:17