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

Dan*_*lho 2 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);
}
Run Code Online (Sandbox Code Playgroud)

如果我执行第一个部分,将打印0,即表达式的计算结果为0.

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

在第三个,将打印1,这意味着表达式不会计算为0.

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

M.M*_*M.M 5

这些代码示例导致未定义的行为,因为t--相对于t表达式的开头没有序列.

这里的排序关系是:

  • t--测序-之前在三元操作者其他表达式
  • 使用返回值之前scanf,每个参数都被排序scanf

但是!=并且-没有排序关系,因此这些关系不限制t在之前进行评估,t--反之亦然,因此行为未定义.


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

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

t--测序,之前的执行scanf机构,因此增量将之前已经平安地结束了scanf潜在的覆盖t.