此 C 代码如何同时评估为 0 而不是 0?

How can this C code evaluate to 0 and not 0 at the same time?

我一直在尝试一些关于代码混淆的竞赛(我知道不是一个很好的编程实践,但这是我和一个朋友竞争的挑战,所以没有必要指出显而易见的),并且在其中一个中,我发现了以下奇怪的行为(代码已经减少到仍然重现表达式 t-scanf("%d",t--?&N:&t):

的行为)
int main(int t, int N){
    printf("%d\n",t-scanf("%d",t--?&N:&t));
}

int main(int t, int N){
    printf("%d\n",t-scanf("%d",t--?&N:&t)==0);
}

int main(int t, int N){
    printf("%d\n",t-scanf("%d",t--?&N:&t)!=0);
}

如果我执行第一段,将打印0,即表达式的计算结果为0。

在第二个上,将打印 0,即表达式不计算 0。

第三次,将打印 1,这意味着表达式的计算结果不为 0。

所以问题是:这些代码有什么问题?

这些代码示例会导致未定义的行为,因为 t-- 相对于表达式开头的 t 是无序的。

这里的顺序关系是:

  • t--sequenced-before 三元运算符中的其他表达式
  • scanf 的每个参数都是 前序 使用 scanf
  • 的 return 值

但是 !=- 没有顺序关系,所以这些关系不限制 tt-- 之前评估,反之亦然,因此行为是未定义。


作为解决方法,您可以编写:

int temp = t;
printf("%d\n", temp - scanf("%d",t--?&N:&t));

t--先于执行scanf主体,因此增量可能会在scanf之前安全完成覆盖 t