gpt4 book ai didi

c - 初学者关于C程序函数调用栈、序列点(sequencing)的疑问

转载 作者:行者123 更新时间:2023-11-30 21:24:35 25 4
gpt4 key购买 nike

下面的代码在 Code::Blocks 上编译和运行时显示不同的结果。

void sum(int a,int b){
printf("a=%d b=%d\n",a,b);
}
int main(){
int i=1;
sum(i=5,++i);
printf("i=%d\n\n",i);
/***********************/
i=2;
sum(i=5,i++);
printf("i=%d\n\n",i);
/**********************/
i=3;
sum(i=5,i);
printf("i=%d\n\n",i);
return 0;
}

输出:

a=5 b=5
i=5

a=5 b=2
i=5

a=5 b=5
i=5

我认为这个问题的答案与序列点有关,而序列点与这里的++运算符有关。 GCC 必须遵循一个顺序,以固定的顺序将值传递到堆栈,但由于++,答案是不同的。我认为对于初学者来说,编写这样的函数调用不是很常见,但是关于运算符的类(class)很通用,因此可以尝试。

我的问题是,它和类似问题的确切答案应该是什么?这些事情是在编译的哪个阶段决定的(明确或不清楚)?涉及哪些特定算法(用于优化或一般)?相同的编译器可以为此类表达式或语句提供不同的结果吗?最后是,初学者如何理解和解决这些问题?有时非常令人惊讶。

最佳答案

操作的顺序是在编译的多个阶段决定的,这就是导致您看到奇怪结果的原因。特别是在优化阶段,编译器可以以并不总是显而易见的方式重新排序代码,在这种情况下,它会影响结果(这很好,因为你正在做一些未定义的事情,并且编译器明确允许做任何它想做的事情与该代码)。不涉及任何特定的算法,它是在不同点应用的几种不同算法之间的交互,并且在每个点应用的算法可能会有所不同,具体取决于编译器决定的处理特定代码位的最佳方法。

当文档谈到未定义的行为时,并不是特定编译器的未定义行为,而是编译器必须或允许执行的操作的规范。编译器的行为是完全定义的,但它是由深埋在其解析器、代码生成器和优化器模块的设计中的详细决策来定义的,而且它非常复杂,即使是编写编译器的开发人员也无法告诉您它会做什么而不花费大量时间分析给定的代码如何在整个过程中流动。

初学者无法弄清楚结果。即使是专家开发人员也可能无法做到。这就是为什么“未定义”对于开发人员来说是一个不受欢迎的词,也是为什么他们像瘟疫一样试图避免未定义的行为。引用有关语言规范的讨论,"In short, you can't use sizeof() on a structure whose elements haven't beendefined, and if you do, demons may fly out of your nose." .

关于c - 初学者关于C程序函数调用栈、序列点(sequencing)的疑问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35817203/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com