tags:

views:

102

answers:

4

This is what I think the ++ operator does

  1. a++; // a+=1 after calculating this line
  2. ++a; // a+=1 before calcuating this line

I'm trying to study pointers, and I think that I misunderstood something.

int a=10;
int arr[3]={0,1,2};
int *ptr;
ptr=arr;

printf("%d,%d,%d,%d\n",a++,a++,++a,++a);
printf("%d,%d,%d\n", ptr[0],ptr[1],ptr[2]);
printf("%d,%d,%d,%d,%d,%d", * ptr++, ( * ptr)++, ++ * ptr, ++( * ptr), *++ptr, * ptr);

I expected that the output to be:

12, 12, 12, 12
0,1,2
3,3,3,3,3,3,3

But it wasn't. It was this:

13,12,14,14
0,1,2
4,3,2,2,2,2

Why is this?

+1  A: 

It's not "per line", it's "per sequence-point" which is similar to "per expression" that the result from pre- and post- increment seem to occur.

In fact, the increment always occurs immediately. The only variation is whether the value of the term will result in the initial or afterward value.

To fully understand that C is not line-oriented, please refer to the standard and read the parts about "sequence points."

Lines which begin with '#' are pre-processor input. The pre-processor for C is line-oriented, but, otherwise, C itself considers the line-break characters the same as any other white space such as tab or space.

Heath Hunnicutt
so how can i seperate an expresstion in that code?
Rhee
As splicer has rewritten your code -- he has separated the increments with semi-colons, which delineate statements in C.
Heath Hunnicutt
+4  A: 

You're not supposed to do more than one increment in arguments to a function.. because the order they can be evaluated in is ambiguous. The result of such code is undefined.

Meaning: printf("%d,%d,%d,%d\n",a++,a++,++a,++a); Should be written as

a++; a++;
++a; ++a;
printf("%d, %d, %d, %d\n", a, a, a, a);

Try and fix that first and see if the results are still confusing.

More generally, you should only have one increment between a pair of sequence points.

Edit: Chris is right, there's no point writing four increments in the middle of nowhere. To better answer your question: For a function void f(int) and void g(int), with int a=0,

f(++a) = f(1);
f(a++) = f(0);
g(++a, ++a) = g(???); // undefined!

So, increment at most once in the argument to a function.

int3
ok ill try, thx!
Rhee
Technically, it _should_ be written as `a += 4`, but then why would we be printing it out 4 times? This code explores undefined behavior, and trying to make it not invoke undefined behavior makes it useless. It's better to say that the code invokes undefined behavior and leave it at that.
Chris Lutz
there is no "supposed to", there is no ambiguity and it is not undefined. It is a matter of evaluation being left to right and pushing into stack being right to left.
Murali VP
Murali, actually splicer is correct -- the order of evaluation is not defined in C compilers. You may be using a compiler that does as you describe. It's behavior may change as you enable optimizations, also.
Heath Hunnicutt
@Murali - It's probably undefined, because GCC issued over 9000 warnings saying "this is probably undefined behavior" when I tried to compile it.
Chris Lutz
Murali: maybe that is how the compiler implements it, but the standard does say you're not supposed to do it.
int3
Yes, I was under the wrong impression, I take back my comment.
Murali VP
+5  A: 

Don't do this. The behavior is undefined.

From the C spec (section 6.5)...

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 accessed only to determine the value to be stored.

Except as indicated by the syntax or otherwise specified later (for the function-call operator () , && , || , ?: , and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified.

In other words, if you update the value of a variable multiple times in the arguments for a function, you're not writing legal C code.

Yuliy
ok that's clear, thx!
Rhee
+3  A: 

See 3.2 in the C FAQ:

3.2: Under my compiler, the code

 int i = 7;
 printf("%d\n", i++ * i++);

prints 49. Regardless of the order of evaluation, shouldn't it print 56?

A: Although the postincrement and postdecrement operators ++ and -- perform their operations after yielding the former value, the implication of "after" is often misunderstood. It is not guaranteed that an increment or decrement is performed immediately after giving up the previous value and before any other part of the expression is evaluated. It is merely guaranteed that the update will be performed sometime before the expression is considered "finished" (before the next "sequence point," in ANSI C's terminology; see question 3.8). In the example, the compiler chose to multiply the previous value by itself and to perform both increments later.

The behavior of code which contains multiple, ambiguous side effects has always been undefined. (Loosely speaking, by "multiple, ambiguous side effects" we mean any combination of increment, decrement, and assignment operators in a single expression which causes the same object either to be modified twice or modified and then inspected. This is a rough definition; see question 3.8 for a precise one, and question 11.33 for the meaning of "undefined.") Don't even try to find out how your compiler implements such things (contrary to the ill-advised exercises in many C textbooks); as K&R wisely point out, "if you don't know how they are done on various machines, that innocence may help to protect you."

References: K&R1 Sec. 2.12 p. 50; K&R2 Sec. 2.12 p. 54; ISO Sec. 6.3; H&S Sec. 7.12 pp. 227-9; CT&P Sec. 3.7 p. 47; PCS Sec. 9.5 pp. 120-1.

Sinan Ünür
Aaaah! Big scary blocks of text!
Chris Lutz
true, now reading these texts for my english aptitude. believe somthing will be better
Rhee
c-faq.com seems to be down and faqs.org does not let me link to individual questions.
Sinan Ünür