我一直在尝试代码混淆的一些竞赛(我知道它是不是一个很好的编程习惯,但这对我来说是一个挑战和一个朋友竞争,所以没有必要指出明显的),并且,在其中一个中,我发现了以下奇怪的行为(代码已被简化为仍然重现行为的一个) 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.
所以问题是:这些代码有什么问题?
答案 0 :(得分:5)
这些代码示例会导致未定义的行为,因为t--
对表达式开头的t
没有排序。
这里的排序关系是:
t--
在三元运算符中的其他表达式之前排序scanf
scanf
的每个参数都在之前排序
但!=
和-
没有排序关系,因此这些关系不会限制t
在t--
之前进行评估,反之亦然,因此行为未定义。
作为一种解决方法,你可以写:
int temp = t;
printf("%d\n", temp - scanf("%d",t--?&N:&t));
t--
在<{1}}正文执行之前排序,因此增量将在scanf
可能覆盖之前安全地完成{{1} }。