例如:
在文件demo.c
中,
#inlcude<stdio.h>
int a = 5;
int main(){
int b=5;
int c=a;
printf("%d", b+c);
return 0;
}
对于int a = 5
,编译器是否将其转换为虚拟内存地址处的存储0x5,例如,const区域中的Ox0000000f
,以便对于int c = a
,它将被翻译类似于movl 0x0000000f %eax
?
然后对于int b = 5
,数字5
不会被放入const区域,而是直接转换为汇编指令中的立即数mov $0x5 %ebx
。
答案 0 :(得分:1)
这取决于。你的程序有几个常量:
int a = 5;
这是一个静态的&#34;初始化(在运行之前加载程序文本和数据时发生)。该值存储在由a
保留的存储器中,该存储器位于读写数据&#34;程序部分&#34;中。如果某些内容发生变化a
,则值5将丢失。
int b=5;
这是一个范围有限的局部变量(仅限main()
)。存储可以是CPU寄存器或堆栈上的位置。为大多数体系结构生成的指令将值5作为&#34;立即数据&#34;放置在x86示例中:
mov eax, 5
指令保持任意常量的能力是有限的。大多数CPU指令都支持小常量。 &#34;大&#34;通常不直接支持常量。在这种情况下,编译器会将常量存储在内存中并加载它。例如,
.psect rodata
k1 dd 3141592653
.psect code
mov eax k1
ARM系列具有强大的设计,可以直接加载大多数常量:任何8位常数值都可以旋转任意偶数次。请参阅this第2-25页。
声明中有一个不那么明显但完全不同的项目:
printf("%d", b+c);
字符串%d
通过现代C语义,是一个由三个char
组成的常量数组。大多数现代实现都会将它存储在只读内存中,以便尝试更改它会导致SEGFAULT,这是一个低级CPU错误,通常会导致程序立即中止。
.psect rodata
s1 db '%', 'd', 0
.psect code
mov eax s1
push eax
答案 1 :(得分:1)
在OP的程序中,a
是“初始化的”“全局”。我希望它放在数据段的初始化部分。请参阅https://en.wikipedia.org/wiki/File:Program_memory_layout.pdf,http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.gif(来自more info on Memory layout of an executable program (process))。 a
的位置由编译器 - 链接器duo决定。
另一方面,作为自动(堆栈)变量,预计堆栈段中会出现b
和c
。
据说,只要未违反观察到的行为(What exactly is the "as-if" rule?),编译器/链接器就可以执行任何优化。例如,如果永远不会引用a
,那么它可能会完全优化。