wha*_*cko 4 c c++ sequence-points
好吧,我真的不是真的需要这个答案,我只是好奇.
类似*ptr++ = a的表达式是完全有效的,因为我们操作两个对象ptr,*ptr但如果我写*ptr++ = *ptr + a它仍然有效?
例如,请考虑以下代码段:
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;
}
Run Code Online (Sandbox Code Playgroud)
我认为表达没有什么可担心的,*p++ = *p + 32;但我不确定所涉及的序列点.
int*_*nt3 12
结果*ptr++ = *ptr + a是未定义的.等号不是序列点,因此ptr在该语句中使用again 的值会导致未定义的行为.只要考虑结果,如果ptr在计算RHS表达式之前递增,并将其与在RHS表达式之后ptr递增的情况进行比较.
注意:这并不是说表达式的结果来自这两种情况中的任何一种.未定义未定义.
基本上,您只能指望两件事:在最后一个序列点和下一个序列点之间的某个时间评估后增量,并且表达式ptr++返回增量ptr 之前的值.所以*ptr++ = a很好,因为你可以指望结果ptr++.
首先让我们假设'p'是指针类型.
否则所有操作都只是函数调用的语法糖.
让我们将声明分解为部分.
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)
Run Code Online (Sandbox Code Playgroud)
鉴于上述限制:
编译器可以通过多种方式重新排序这些指令,
但需要注意的是,(B)可能发生在(B)的唯一约束条件下它发生在(A)之后的任何地方. (D)中定义的p3可以是两个不同值中的一个,这取决于(B)的确切位置.
由于此处无法定义p3的值.
结果语句具有未定义的行为.