C语言中c = a && b << --a等表达式是否属于未定义行为?
表达式未定义行为的分析
先纠正一个误解:b = 5 << sizeof(a++);不是未定义行为
C语言里,sizeof的操作数如果是表达式,这个表达式不会被实际执行——说白了a++这步自增根本没机会跑,a的值纹丝不动。所以这个表达式完全合法,不存在未定义行为。
看c = a && b << --a;的情况
&&是短路逻辑运算符,规则很明确:
- 先算左边的
a,读一次a的值; - 左边算完后,会有一个序列点(可以理解为所有之前的操作必须彻底完成的节点);
- 只有左边结果非0时,才会算右边的
b << --a:这里--a会改a的值,但因为序列点已经把“读a”和“改a”的操作彻底隔开了,顺序是确定的,不会出现编译器乱序的情况。
所以这个表达式没有未定义行为。
再看c = a || b << a++;的情况
||和&&是一路的,都是短路运算符:
- 先算左边的
a,读一次a的值; - 左边算完触发序列点;
- 只有左边结果为0时,才会算右边的
b << a++:a++改a的值,同样因为序列点的存在,读和改的顺序被明确下来,操作是确定的。
这个表达式也不存在未定义行为。
额外提一句:真正的未定义行为场景
只有当同一个表达式里,对同一个变量的多次修改,或者修改和读操作之间没有序列点隔开时,才会出问题。比如a = a++、printf("%d %d", a, ++a)这类代码,编译器想怎么调顺序就怎么调,结果完全不可预测,这才是标准里说的未定义行为。
内容的提问来源于stack exchange,提问作者s96
相关产品推荐
相关产品推荐

