问题
I am receiving a lot of conflicting answers about this. But as I always understood it.
When we have a pointer in C and use it in a post increment statement, the post increment will always happen after the line of code resolves.
int array[6] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *p++); // This will output 0 then increment pointer to 1
output :
0
Very simple stuff. Now here's where I am receiving a bit of dissonance in the information people are telling me and my own experience.
// Same code as Before
int array[0] = {0,1,2,3,4,5};
int* p = array;
printf("%d", *(p++)); // Issue with this line
output :
0
Now when I run that second version of the code The result is that it will output 0 THEN increments the pointer. The order of operations implied by the parentheses seems to be violated. However some other answers on this site tell me that the proper thing that should happen is that the increment should happen before the dereference. So I guess my question is this: Is my understanding correct? Do post increment statements always execute at the end of the line?
Additional Info:
I am compiling with gcc on linux mint with gcc version ubuntu 4.8.4
I have also tested this on gcc on debian with version debian 4.7.2
回答1:
OP's "The result is that it will output 0 THEN increments the pointer." is not correct.
The postfix increment returns the value of the pointer. Consider this value as a copy of the original pointer's value. The pointer is incremented which does not affect the copy.
The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented. ... C11dr 6.5.2.4 2
Then the copy of the pointer is de-referenced and returns the 0
. That is the functional sequence of events.
Since the side-effect of incrementing the pointer and de-referencing that copy of the pointer do not effect each other, which one occurs first is irrelevant. The compiler may optimized as it likes.
"the end of the line" is not involved in code. It is the end of the expression that is important.
回答2:
There is no difference in meaning between *p++
and *(p++)
.
This is because postfix operators have a higher precedence than unary operators.
Both these expressions mean "p
is incremented, and its previous value is dereferenced".
If you want to increment the object being referenced by the pointer, then you need to override precedence by writing (*p)++
.
No version of your code can produce output and then increment p
. The reason is that p
is incremented in an argument expression which produces a value that is passed into printf
. In C, a sequence point occurs just before a function is called. So the new value of p
must settle in place before printf
executes. And the output cannot take place until printf
is called.
Now, you have to take the above with a slight grain of salt. Since p
is a local variable, modifying it isn't an externally visible effect. If the new value of p
isn't used anywhere, the increment can be entirely optimized away. But suppose we had an int * volatile p;
at file scope, and used that instead. Then the expression printf("...", *p++)
has to increment p
before printf
is called.
回答3:
The expression p++
has a result (the value of p
before the increment) and a side effect (the value of p
is updated to point to the next object of type int
).
Postfix ++
has higher precedence than unary *
, so *p++
is already parsed as *(p++)
; you will see no difference in behavior between those two forms. IOW, the dereference operator is applied to the result of p++
; the line
printf("%d", *p++);
is roughly equivalent to
printf("%d", *p);
p++;
with the caveat that p
will actually be updated before the call to printf
1.
However, (*p)++
will be different; instead of incrementing the pointer, you are incrementing the thing p
points to.
1. The side effect of a
++
or --
operator must be applied before the next sequence point, which in this particular case occurs between the time the function arguments are evaluated and the function itself is called.
回答4:
Here is my take on this. Let's ignore the printf function altogether and make things simpler.
If we said
int i;
int p=0;
i = p++;
Then i would be equal to zero because p was equal to zero but now p has been incremented by one; so now i still equals zero and p is equal to 1.
Ignoring the declarations of i and p as integers, if we wrap this as in the example, i = *(p++)
, then the same action occurs but i now contains the value pointed at by p which had the value of zero. However, the value of p, now, has been incremented by one.
来源:https://stackoverflow.com/questions/35733484/what-happens-when-you-dereference-a-postincrement-c