You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

这段存在未定义行为的C代码输出是否具有编译器依赖性?

问题分析

给出的代码如下:

#include <stdio.h>

int main(void)
{ 
   int a = 0, b = 1;
   a = (a = 5) && (b = 0);
   printf("%d", a);
   printf("%d", b);
}

你的判断有误——这段代码并不存在未定义行为,所以输出是确定的,和编译器无关,所有符合C标准的编译器都会输出00。

关键原因:逻辑与运算符的序列点和短路求值

C标准规定,逻辑与运算符&&有两个关键特性:

  • 短路求值:如果左操作数的求值结果为假(0),则右操作数不会被求值;如果左操作数为真(非0),才会继续求值右操作数。
  • 序列点:在左操作数的求值完成后、右操作数的求值开始前,存在一个序列点。序列点的意义是:在这个点之前的所有表达式的副作用(比如变量赋值)都已经完全生效,之后的副作用不会影响之前的结果。

回到代码中的表达式a = (a = 5) && (b = 0),执行顺序是严格确定的:

  1. 先计算左操作数(a = 5):将a赋值为5,该表达式的返回值是5(非0,即逻辑真)。
  2. 由于左操作数为真,触发&&的右操作数求值,此时序列点已经确保a=5的副作用完全生效。
  3. 计算右操作数(b = 0):将b赋值为0,该表达式的返回值是0(逻辑假)。
  4. 计算&&的结果:5 && 0 = 0,然后将这个结果赋值给a,此时a被更新为0。
  5. 最后两次printf分别输出a的值0和b的值0,所以最终输出是00。

为什么你会误以为是未定义行为?

你可能混淆了“无序列点情况下的多次变量修改”。比如像a = a++这样的表达式,两次修改a之间没有序列点,才属于未定义行为,结果由编译器决定。但在这段代码里,a=5和后续的a=...之间被&&的序列点隔开,完全符合C标准的规则,所以行为是确定的。

内容的提问来源于stack exchange,提问作者SUBHAJIT PAUL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:07:13