C语言复合赋值运算符:下述程序的输出是什么?为什么?
这段C语言程序的输出与原因分析
首先直接给结论:在GCC、Clang这类常见编译器的默认设置下,程序的输出是28,但必须严肃说明:这个结果并不是C语言标准所保证的——这段代码存在未定义行为,更换编译器、调整编译选项都可能得到完全不同的输出,甚至出现运行异常。
编译器常见的计算逻辑(仅为实现行为,非标准规定)
复合赋值运算符+=是右结合的,所以多数编译器会按照从右到左的顺序拆解计算表达式a += a += a += 2:
- 第一步:计算最右侧的
a += 2,初始a=5,执行后a = 5 + 2 = 7 - 第二步:计算中间的
a += 7(用上一步的结果作为右操作数),此时a = 7 + 7 = 14 - 第三步:计算最左侧的
a += 14,最终a = 14 + 14 = 28
最后printf输出这个值,这就是你大概率会看到的结果。
为什么这是未定义行为?
根据C语言标准,当同一个表达式中对同一个变量的多次修改操作之间没有序列点分隔时,程序的行为是完全未定义的。
- 序列点是程序执行的一个节点,能保证在这个节点之前的所有表达式求值、变量修改等副作用全部完成,之后的操作才会开始。
- 在
a += a += a += 2里,三个+=操作都会修改a的值,但它们之间没有序列点。这意味着编译器可以自由选择求值顺序:比如有些编译器可能会先读取a的初始值5,再依次计算所有部分,最终得到5 + (5 + (5+2)) = 17;极端情况下甚至可能出现不可预测的结果。 - 未定义行为的本质是C标准不对这类代码的行为做任何承诺,所以这种写法绝对不能用于实际项目中。
内容的提问来源于stack exchange,提问作者Kaustubh Dange
相关产品推荐
相关产品推荐

