“C”语句如何在内存中执行

“C”语句如何在内存中执行,c,statements,C,Statements,假设我这里有一段C代码: int main() { int a = 10; printf("test1"); printf("test2"); someFunc(); a = 20; printf("%d",a); } 我认为所有这些语句一次存储在堆栈上,然后逐个弹出以执行。我说得对吗?如果没有,请更正。不是真的没有。C标准没有提到堆栈,因此您的想法是错误的 只要遵循C标准,C编译器或解释器就可以做任何它喜欢做的事情 在你

假设我这里有一段C代码:

int main() {           
    int a = 10;
    printf("test1");
    printf("test2");
    someFunc();
    a = 20;
    printf("%d",a);
} 

我认为所有这些语句一次存储在堆栈上,然后逐个弹出以执行。我说得对吗?如果没有,请更正。

不是真的没有。C标准没有提到堆栈,因此您的想法是错误的

只要遵循C标准,C编译器或解释器就可以做任何它喜欢做的事情

在你的例子中,这可能意味着,除其他外,i完全删除a,因为它只用于在函数末尾输出20,ii someFunc可以删除,如果这样做没有副作用


通常情况下,您的代码会转换为适合目标体系结构的机器代码。这些机器代码指令确实倾向于非常忠实地遵循代码。从这个意义上讲,C的级别相当低,尽管现代编译器会积极地进行优化。

不太可能。C标准没有提到堆栈,因此您的概念是不正确的

只要遵循C标准,C编译器或解释器就可以做任何它喜欢做的事情

在你的例子中,这可能意味着,除其他外,i完全删除a,因为它只用于在函数末尾输出20,ii someFunc可以删除,如果这样做没有副作用


通常情况下,您的代码会转换为适合目标体系结构的机器代码。这些机器代码指令确实倾向于非常忠实地遵循代码。从这个意义上说,C的级别相当低,尽管现代编译器会积极地进行优化。

值得注意的是,C标准并不强制执行。因此,只要输出符合标准,编译器就可以自由地实现它所选择的功能

对您来说,最可能发生的情况是编译器将这段C转换成汇编代码,然后自上而下执行

a = 20;
除非您在其他地方使用它,否则它很可能已优化。好的编译器也会给你一个警告,比如:

警告:未使用的变量a


值得注意的是,C标准并不强制执行。因此,只要输出符合标准,编译器就可以自由地实现它所选择的功能

对您来说,最可能发生的情况是编译器将这段C转换成汇编代码,然后自上而下执行

a = 20;
除非您在其他地方使用它,否则它很可能已优化。好的编译器也会给你一个警告,比如:

警告:未使用的变量a


C标准没有指定内存中的内容

然而,计算机通常是这样工作的:

您的程序由各种内存段组成,通常称为.data、.bss、.rodata、.stack、.text,还可能有一个.heap。.text部分用于存储实际的程序代码,其余部分用于存储变量。 编译器将C代码翻译成机器代码汇编程序。所有代码都存储在.text节中,该节是只读内存。 现代计算机可以将内存标记为代码或数据,如果您试图在数据部分执行代码,或将代码部分视为数据,则可以生成硬件异常。通过这种方式,处理器可以帮助捕获诸如悬空指针或失控代码之类的bug。 理论上,您可以从任何内存段执行代码,即使是在堆栈上,但由于前面提到的特性,这通常不会执行。大多数情况下,无论如何这样做都没有任何意义。 因此,对于特定的代码段,堆栈上存储的唯一内容是变量a。或者更可能的是,出于性能原因,它存储在CPU寄存器中

字符串文本test1、test2和%d将存储在.rodata节中

文字20可以存储在.rodata部分,或者更可能合并到代码中,因此与代码的其余部分一起存储在.text中


程序计数器确定当前执行的代码部分。堆栈与此无关,它只用于存储数据。

C标准没有指定内存中的内容

然而,计算机通常是这样工作的:

您的程序由各种内存段组成,通常称为.data、.bss、.rodata、.stack、.text,还可能有一个.heap。.text部分用于存储实际的程序代码,其余部分用于存储变量。 编译器将C代码翻译成机器代码汇编程序。所有代码都存储在.text节中,该节是只读内存。 现代计算机可以将内存标记为代码或数据,如果您试图在数据段中执行代码,或处理 e代码部分作为数据。通过这种方式,处理器可以帮助捕获诸如悬空指针或失控代码之类的bug。 理论上,您可以从任何内存段执行代码,即使是在堆栈上,但由于前面提到的特性,这通常不会执行。大多数情况下,无论如何这样做都没有任何意义。 因此,对于特定的代码段,堆栈上存储的唯一内容是变量a。或者更可能的是,出于性能原因,它存储在CPU寄存器中

字符串文本test1、test2和%d将存储在.rodata节中

文字20可以存储在.rodata部分,或者更可能合并到代码中,因此与代码的其余部分一起存储在.text中


程序计数器确定当前执行的代码部分。堆栈与此无关,它仅用于存储数据。

通常,编译器将代码转换为机器代码,然后CPU自上而下执行机器代码,而不考虑跳转。局部变量通常存储在堆栈上,CPU机器指令则不是。几乎所有的编译器都有将生成的机器代码保存为汇编代码的选项,汇编代码是使用CPU指令的好名称的机器代码,您可能想看看这一点,并进一步了解它。我还建议您多读一些关于计算机底层体系结构的知识,以及它们如何在内部工作。他们只读到我强烈建议任何想成为程序员的人学习基本汇编程序,了解程序和计算机的实际工作原理。除非你知道这一点,否则你不是真正的程序员——这与你不是汽车修理工的原因是一样的,因为你会开车。@Lundin谢谢你的建议……我真的很感激……通常代码由编译器翻译成机器代码,然后CPU自上而下执行机器代码,而不考虑跳跃。局部变量通常存储在堆栈上,CPU机器指令则不是。几乎所有的编译器都有将生成的机器代码保存为汇编代码的选项,汇编代码是使用CPU指令的好名称的机器代码,您可能想看看这一点,并进一步了解它。我还建议您多读一些关于计算机底层体系结构的知识,以及它们如何在内部工作。他们只读到我强烈建议任何想成为程序员的人学习基本汇编程序,了解程序和计算机的实际工作原理。除非你知道这一点,否则你不是真正的程序员——原因与你不是汽车修理工的原因相同,因为你会开车。@Lundin谢谢你的建议……我真的很感激……我喜欢你的解释,但我想说得更清楚。只是为了防止递归调用,方法中递归调用后的语句存储在堆栈中,这些语句不可能以相同的方式执行吗?存储在堆栈中并被弹出…请解释可能会这样做。另一方面,编译器可能会取消对递归的点击,特别是如果它发现了尾部递归。是的,在尾部递归的情况下,可能是因为递归调用后没有任何内容。因此,简而言之,编译器如何执行上述代码没有保证。我对吗?是的。根本不能保证。只是保证遵守C标准。@Calculater的实现永远不能得到保证。唯一可以信赖的是编译器遵循c标准。介于两者之间的任何事情都取决于编译器。我喜欢你的解释,但我想让自己更清楚。只是在递归调用的情况下,方法中递归调用后的语句存储在堆栈中,这些语句不可能以相同的方式执行吗?存储在堆栈中并被弹出……请解释可能会这样做。另一方面,编译器可能会取消对递归的点击,特别是如果它发现了尾部递归。是的,在尾部递归的情况下,可能是因为递归调用后没有任何内容。因此,简而言之,编译器如何执行上述代码没有保证。我对吗?是的。根本不能保证。只是保证遵守C标准。@Calculater的实现永远不能得到保证。唯一可以信赖的是编译器遵循c标准。介于两者之间的任何内容都由编译器决定。