Is this “*ptr++ = *ptr + a” undefined behavior?

ぐ巨炮叔叔 提交于 2019-12-06 04:13:07

问题


Well, I'm not really in serious need of this answer, I am just inquisitive.

Expressions like *ptr++ = a are perfectly valid since we are operating on two objects ptr and *ptr but if i write *ptr++ = *ptr + a is it still valid ?

For example consider the following snippet:

int main(void){
   int a[] = {5,7,8,9,2};

   int* p =a;

   *p++ = 76; /*altering the first element */
   *p++ = *p + 32; /*altering the second element */    

   p = a;
   int i;
   for(i = 0;i<5; i++)
      printf("%d ",*p++);

   return 0;
}

I think that there is nothing to worry about with the expression *p++ = *p + 32; but I am unsure about the sequence points involved.


回答1:


First let us assume that 'p' is a pointer type.
Otherwise all the operation are just syntactic sugar for function calls.

Lets us break the statement down into parts.

int* p = a;

*p++ = *p + 32;

<< Sequence Point >>
// Part 1: p++
// Note the definition of post increment in the standard is (5.2.6)
// The result of the expression p++ is the value of 'p' while the value of the 
// objects represented by 'p' is incremented. This can be represented in pseudo code as:
(A) int*  p1 = p;
(B) p = p + 1;

// Part 2: *p (On the result of Part 1) (On *p++)
(C) int& p2 = *p1;  // Note the use of p1;

// Part 3: *p (On *p + 32)
// Note: There is no linkage between this use of 'p' and the 'p' in Part 1&2
(D) int& p3 = *p;

// Part 4: *p + 32;
(E) int p5 = p3 + 32; // Note the use of p3;

// Part 5: Assignment.
(F) p2 = p5;
<< Sequence Point >>

Ordering that must be preserved:
(A) Before (B)
(A) Before (C)
(D) Before (E)
(C) Before (F)
(E) Before (F)

Given the above constraints:
The compiler can re-order those instructions in several ways,
But the main point to note is that (B) can happen anywhere the only constraint on (B) is that it happen after (A) Thus the value of p3 as defined in (D) could be one of two different values depending on the exact position of (B).

As the value of p3 can not be defined here.
The resulting statement has undefined behavior.




回答2:


The result of *ptr++ = *ptr + a is undefined. The equals sign is not a sequence point, so using the value of ptr again in that statement results in undefined behavior. Just consider the result if ptr is incremented before the RHS expression is evaluated, and compare it with the case where ptr is incremented after the RHS expression.

Note: this is not to say that the result of the expression will be from either of those two scenarios. Undefined is undefined.

Basically, you can only count on two things: that the post-increment is evaluated some time between the last sequence point and the next one, and that the expression ptr++ returns the value of ptr before it is incremented. So *ptr++ = a is fine because you can count on the result of ptr++.




回答3:


In terms of C, *ptr++ = *ptr + 32 would be undefined per 6.5.2: "If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined." You're both modifying and attempting to use the value of ptr in another computation without an intervening sequence point.




回答4:


I think it is undefined. However I'm not certain.

But, a bit of a broader stylistic point: if an expression makes you start to wonder if it's undefined, maybe this is a sign your code is not clear about its intentions and needs to be less ambiguous, and have fewer non-obvious dependencies on order of evaluation.

I used to think C was really cool because you could write a lot of very short statements that do lots of crazy stuff. I don't think that way anymore. :-)




回答5:


There are not the same if that what you're asking. It will compile though...

It is legal - if PTR points to an array, and not on the last cell of that array, so incrementing PTR will point to the next object in the array.

*ptr++ = *ptr + 2 is the same as *ptr = *ptr + 2, ptr++



来源:https://stackoverflow.com/questions/1831316/is-this-ptr-ptr-a-undefined-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!