2

can someone provide me more insight on why this code works the way it works

#include <stdio.h>

int main()
{
    int a[5] = {1,2,3,4,5};
    int i;
    for(i=0;i<5;i++)
    {
     printf("%d,%d \n",i[a],i[a]++);
    }
    return 0;
}

The result is

2,1 
3,2 
4,3 
5,4 
6,5 

Thanks

SP6
  • 119
  • 9
  • 1
    Where did you find that code? If it's in a book, please stop reading, it's hurting you. `i[a]++` is just plain evil. – Mat Sep 28 '11 at 19:58
  • its a quiz sort of thing. I havent seen that in any book and thats why I reached out to the folks here. – SP6 Sep 28 '11 at 19:59
  • 1
    It does not have "void main()" so it cannot be Herb Schildt ;-) – wildplasser Sep 28 '11 at 20:01
  • 2
    Before anyone wonders why it's `index[array]` instead of `array[index]` and still works (well, *that* part works - the program as a whole has UB), see http://stackoverflow.com/questions/381542/in-c-arrays-why-is-this-true-a5-5a. –  Sep 28 '11 at 20:01
  • @delnan : +1 for getting to the heart of it :) – Hugh Jones Sep 28 '11 at 20:32
  • so a followup question - Is this seen commonly (cause this is the first time I have faced/seen this) and does it happen for any function or printf() in particular – SP6 Sep 28 '11 at 20:54
  • @KeithThompson: a professor asked it. – SP6 Sep 28 '11 at 20:56
  • Painfully ugly code like that is more commonly seen than it should be, but not all *that* often. The problem is going to occur any time one function argument modifies an object and another reads it. ***So don't do that.*** – Keith Thompson Sep 28 '11 at 21:06

3 Answers3

5

The behavior is undefined.

N1256 6.5p2:

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

The program both modifies i[a] (in i[a]++) and reads its value (in the next argument), and the result of reading the value is not used to determine the value to be stored.

This is not just a matter of the unspecified order of evaluation of function arguments; the fact that there's no sequence point between i[a]++ and i[a] (since that's not a comma operator) means that the behavior, not just the result, is undefined.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Which means trying to figure out *why* you get a particular result is largely a waste of time; it can vary based on platform, compiler, compiler settings, surrounding code, etc. Whether by accident or design, whatever the compiler does *at that particular moment* is "okay". – John Bode Sep 28 '11 at 20:56
  • Well, it can sometimes be useful to diagnose why a program is producing a particular result. The ideal solution, of course, is to fix the code, but that can be a very involved process. – Keith Thompson Sep 28 '11 at 21:08
  • To be fair, some others actually answered the question more directly than I did. – Keith Thompson Sep 28 '11 at 21:10
  • From _What Every C Programmer Should Know About Undefined Behavior_ series at the LLVM Project Blog, "any undefined behavior in C gives license to the implementation (the compiler and runtime) to produce code that formats your hard drive, does completely unexpected things, or worse." http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html – Shannon Severance Sep 28 '11 at 21:16
  • I upvoted for, "This is not just a matter of the unspecified order of evaluation of function arguments; ... " I don't think the other answers made that clear. – Shannon Severance Sep 28 '11 at 21:17
2

It works by undefined behaviour. The order of evaluation of function arguments is not defined. The comma is not a sequence point.

EDIT: ooops, I read to fast. There is only one write to the a[i] object, so the behaviour is not undefined, only the results.

wildplasser
  • 43,142
  • 8
  • 66
  • 109
  • 1
    "The comma is not a sequence point." is correct in context, but can be misunderstood so I plea for clarification. The comma *operator*, which is very much seperate from the comma in argument lists, parameter lists, etc. *is* a sequence point. That's it's main use. –  Sep 28 '11 at 20:04
  • 1
    Sorry. I just corrected it. I meant: **this** comma. But that's not the real issue. The real issue is order of evaluation of function arguments. – wildplasser Sep 28 '11 at 20:07
0

"i[a]++" is a post increment, so it will return the value of i[a] and then increment i[a] right away.

In your case, the third parameter of printf gets evaluated before the second (the evaluation order of function parameters is unspecified as far as I know), and thus the second parameter returns the already incremented value.

Shautieh
  • 746
  • 10
  • 17