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

为什么(* p = * p)& (* Q = * Q);如果p和q相等,则在C中触发未定义的行为.
int f2(int * p,int * q)
{
  (*p=*p) & (*q=*q);
  *p = 1;
  *q = 2;
  return *p + *q;
}

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

解决方法

C11标准对该声明的裁决
(*p=*p) & (*q=*q);

是:

P1

§6.5p3

The grouping of operators and operands is indicated by the Syntax. 85) Except as specified later,side effects and value computations of subexpressions are unsequenced.

由于§6.5.10BitwiseAND运算符未提及其操作数的排序,因此(* p = * p)和(* q = * q)未被排序.

P2

§6.5p2

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. If there are multiple allowable orderings of the subexpressions of an expression,the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. 84)

两个赋值(* p = * p)和(* q = * q)都没有序列w.r.t.相互§6.5p3,如果p == q,则对同一个对象产生副作用.因此,那么通过§6.5p2我们有UB.

P3

§3.4.3

undefined behavIoUr

behavior,upon use of a nonportable or erroneous program construct or of erroneous data,for which this International Standard imposes no requirements.

根据这一条款,我们知道该标准对UB没有任何要求.这通常被编译器解释为忽略发生此类行为的可能性的许可.

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

P1 P2 P3 – > C1

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

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...