这个C代码如何评估为0而不是0?

时间:2015-02-26 00:25:15

标签: c obfuscation sequence-points

我一直在尝试代码混淆的一些竞赛(我知道它是不是一个很好的编程习惯,但这对我来说是一个挑战和一个朋友竞争,所以没有必要指出明显的),并且,在其中一个中,我发现了以下奇怪的行为(代码已被简化为仍然重现行为的一个) 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.

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

1 个答案:

答案 0 :(得分:5)

这些代码示例会导致未定义的行为,因为t--对表达式开头的t没有排序。

这里的排序关系是:

  • t-- 三元运算符中的其他表达式之前排序
  • 使用scanf
  • 的返回值,scanf的每个参数都之前排序

!=-没有排序关系,因此这些关系不会限制tt--之前进行评估,反之亦然,因此行为未定义。


作为一种解决方法,你可以写:

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

t-- 在<{1}}正文执行之前排序,因此增量将在scanf可能覆盖之前安全地完成{{1} }。