

So you think you know C?  - dmk23

Solve this multiple choice puzzle and explain your answer<p><pre><code>  int i = 5;
  i = ++i + ++i;
  return i;

  a) 12
  b) 13
  c) 14
  d) Undefined</code></pre>
======
zellio
The answer is D, D a thousand times D.

Firstly, from Wikipedia

A sequence point defines any point in a computer program's execution at which
it is guaranteed that all side effects of previous evaluations will have been
performed, and no side effects from subsequent evaluations have yet been
performed.

\-----

Secondly from Annex C of the C99 Standard: Sequence Points

1\. The following are sequence points described in 5.1.2.4

\- The call to a function, after the arguments have been evaluated (6.5.2.2).

\- The end of the first operand of the following operators: logical AND &&
(6.5.13); logical OR || (6.5.14); conditional ? (6.5.17).

\- The end of a full declarator: declarators (6.7.5);

\- The end of a full expression: an initializer (6.7.8); the expression in an
expression statement (6.8.3); the controlling expression for a while or do
statement (6.8.5); each of the expressions fro a for statement (6.8.5.3); the
expression in a return statement (6.8.6.4).

\- Immediately before a library function returns (7.1.4).

\- After the actions associated with each formatted input/output function
conversion specified (7.19.6, 7.24.2).

\- Immediately before and immediately after each call to a comparison function
and also between any call to a comparison function and any movement of the
object passed as arguments to the call (7.20.5).

\-----

Now onto this statement

i = ++i + ++i;

lacking in sequence points between the double assignments is undefined and has
been undefined for the life of the language. It is as undefined as all of it's
ugly brethren and should be left to die.

Why does this question keep popping up?

~~~
crpatino
> The answer is D, D a thousand times D.

Do you mean option D or D, the Language?

~~~
zellio
Option D, the language, while interesting, doesn't really have any bearing on
the question.

------
mds
I get that the answer is "undefined". But I decided to figure out why at least
on my compiler I get "14".

    
    
        $ cat t.c ; gcc ./t.c
    
        #include<stdio.h>
        int main() {
            printf("%d\n", a());
        }
    
        int a() {
            int i = 5;
            i = ++i + ++i;
            return i;
        }
        $ ./a.out
        14 # ??
    
        $ gcc t.c -c -o t.bin
        $ gdb t.bin
        ...
        (gdb) disassemble a
        Dump of assembler code for function a:
        0x0000000000000030 <a+0>:	push   %rbp
        0x0000000000000031 <a+1>:	mov    %rsp,%rbp
        0x0000000000000034 <a+4>:	movl   $0x5,-0xc(%rbp)
        0x000000000000003b <a+11>:	mov    -0xc(%rbp),%eax
        0x000000000000003e <a+14>:	add    $0x1,%eax            # add 1 and store it in i => 6
        0x0000000000000041 <a+17>:	mov    %eax,-0xc(%rbp)
        0x0000000000000044 <a+20>:	mov    -0xc(%rbp),%eax
        0x0000000000000047 <a+23>:	add    $0x1,%eax            # add 1 and store it in i => 7
        0x000000000000004a <a+26>:	mov    %eax,-0xc(%rbp)       
        0x000000000000004d <a+29>:	mov    -0xc(%rbp),%eax
        0x0000000000000050 <a+32>:	mov    -0xc(%rbp),%ecx      # move current value of i (7) into %ecx and %eax (both registers are now 7) 
        0x0000000000000053 <a+35>:	add    %ecx,%eax            # add them together => 14
        0x0000000000000055 <a+37>:	mov    %eax,-0xc(%rbp)

...

------
bandy
Which version of C? The answers vary. For 1st ed. K&R, you're going to get
implementation-specific behaviour, which might very well vary whether or not
optimization is enabled.

~~~
jrajav
"Implementation-specific behavior [..] which might very well vary"

In other words, the very definition of _undefined_ behavior; You cannot reason
about how the program will behave. This topic has already been covered fairly
well on SO: [http://stackoverflow.com/questions/949433/could-anyone-
expla...](http://stackoverflow.com/questions/949433/could-anyone-explain-
these-undefined-behaviors-i-i-i-i-i-etc)

~~~
Someone
Not quite. C and C++ standards discriminate between undefined- and
implementation-defined behavior. In the latter case, implementaitons can
differ, but each must choose (and document) some well-defined way to handle a
case. A trivial example is "sizeof(int)". The standard does not say much about
what it produces (IIRC, it must be an int at least as large as sizeof(char)),
so it can return 1, 2, 4, or even 17 (well, maybe not in C11. Newer standards
tend to put more restrictions on behavior)

A nontrivial example is the value of "-64 >> 3". More info at
[http://stackoverflow.com/questions/2397984/undefined-
unspeci...](http://stackoverflow.com/questions/2397984/undefined-unspecified-
and-implementation-defined-behavior)

I think the post you reply to refers to the fact that early K&R C predates any
standard that introduced the term 'undefined behavior'. At that time, the
standard was just 'whatever that tool Kernighan and Ritchie wrote does'.

~~~
bandy
Even at that point, there was the PDP-11 compiler and the compiler for the
Perkins-Elmer implementation, not to mention the (straight) C compiler
(/usr/bin/cc) vs the Portable C Compiler, both of which were available on V7.

The maxim then (and now) being: Don't Write Silly Code.

------
jaysonsantos
The weirdest thing happens when you compile it with gcc and then try it with
clang. <http://pastebin.com/DwFgsiLV>

------
anigbrowl
b). ++i increments i before the equality operation and is evaluated inline.

PS why, are you having hiring difficulties or something?

~~~
dmk23
Not having any difficulties, just ran into this problem and thought it would
be fun to share with HN.

By the way your answer is wrong.

~~~
elclanrs
How come? b) seems correct in my book.

~~~
zellio
B may seem like it is the "correct" answer, in so much as you are getting that
out of your test programs. But because this code is undefined the
functionality is compiler dependent and cannot be counted on. It is liable to
change at a moment's notice and shouldn't make it into production code.

The C spec doesn't handle this case. The only correct answer is undefined.

