此 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 值
但是 !=
和 -
没有顺序关系,所以这些关系不限制 t
在 t--
之前评估,反之亦然,因此行为是未定义。
作为解决方法,您可以编写:
int temp = t;
printf("%d\n", temp - scanf("%d",t--?&N:&t));
t--
先于执行scanf
主体,因此增量可能会在scanf
之前安全完成覆盖 t
。
我一直在尝试一些关于代码混淆的竞赛(我知道它不是一个很好的编程实践,但这是我和一个朋友竞争的挑战,所以没有必要指出显而易见的),并且在其中一个中,我发现了以下奇怪的行为(代码已经减少到仍然重现表达式 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 值
但是 !=
和 -
没有顺序关系,所以这些关系不限制 t
在 t--
之前评估,反之亦然,因此行为是未定义。
作为解决方法,您可以编写:
int temp = t;
printf("%d\n", temp - scanf("%d",t--?&N:&t));
t--
先于执行scanf
主体,因此增量可能会在scanf
之前安全完成覆盖 t
。