为什么(*p =*p)&(*q =*q); 在C中触发未定义的行为

naw*_*bgh 6 c pointers undefined-behavior sequence-points

为什么(*p=*p) & (*q=*q);在当C触发未定义行为pq相等.

int f2(int * p, int * q)
{
  (*p=*p) & (*q=*q);
  *p = 1;
  *q = 2;
  return *p + *q;
}
Run Code Online (Sandbox Code Playgroud)

来源(顺便说一句好文章):http://blog.frama-c.com/index.php?post/2012/07/25/On- the- redundancy-of-C99-s-restrict

Iwi*_*ist 4

C11标准对声明的裁决

\n
(*p=*p) & (*q=*q);\n
Run Code Online (Sandbox Code Playgroud)\n

是:

\n

P1

\n
\n

\xc2\xa76.5p3

\n

运算符和操作数的分组由语法指示。85) 除非稍后指定,否则子表达式的副作用和值计算是无序的。

\n
\n

由于\xc2\xa76.5.10 按位 AND 运算符未能提及其操作数的排序,因此它遵循(*p=*p)(*q=*q)未排序。

\n

P2

\n
\n

\xc2\xa76.5p2

\n

如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值的值计算是无序的,则行为是未定义的。如果表达式的子表达式有多个允许的排序,并且在任何排序中出现此类未排序的副作用,则行为未定义。84)

\n
\n

两个赋值(*p=*p)(*q=*q)都通过 \xc2\xa76.5p3 彼此不排序,并且对同一个对象 if 产生副作用p==q。因此,如果p==q,则通过 \xc2\xa76.5p2 我们得到 UB。

\n

P3

\n
\n

\xc2\xa73.4.3

\n

未定义的行为

\n

使用不可移植或错误的程序结构或错误数据时的行为,本国际标准对此没有强加任何要求。

\n
\n

通过该条款我们知道该标准对UB没有任何要求。编译器通常将其解释为忽略发生此类行为的可能性的许可。

\n

特别是,它允许编译器不处理 case p == q,这意味着它可以假设p != q

\n

P1+P2+P3 -> C1

\n

因为组合前提P1、P2和P3可以假定不调用UB,所以它们也可以被假定为加载和存储到不同的存储器位置(*p=*p)(*q=*q)这也意味着 的返回值f2必须是3并且不是4。如果p == q,则标准对发生的情况没有施加任何要求。

\n