常量数据存储在哪里

Where is const data stored?

本文关键字:在哪里 存储 数据 常量      更新时间:2023-10-16

例如:

在文件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 一样直接翻译成汇编指令中的立即

这取决于。 程序有几个常量:

int a = 5;

这是一个"静态"初始化(在运行之前加载程序文本和数据时发生)。 该值存储在a保留的内存中,该内存位于读写数据"程序部分"中。 如果某些东西a发生变化,则值 5 将丢失。

int b=5;

这是一个范围有限的局部变量(仅按 main() )。 存储很可能是 CPU 寄存器或堆栈上的某个位置。 对于 x86 示例,为大多数体系结构生成的指令会将值 5 作为"即时数据"放在指令中:

mov   eax, 5

指令保存任意常量的能力是有限的。 大多数 CPU 指令都支持小常量。 通常不直接支持"大"常量。 在这种情况下,编译器会将常量存储在内存中并加载它。 例如

       .psect  rodata
k1     dd      3141592653
       .psect  code
       mov     eax  k1

ARM 系列具有可直接加载大多数常量的强大设计:任何 8 位常量值都可以旋转任意偶数次。 请参阅第 2-25 页。

声明中有一个不那么明显但完全不同的项目:

printf("%d", b+c);

根据现代 C 语义,字符串%d是一个由三个char组成的常量数组。 大多数现代实现会将其存储在只读内存中,因此尝试更改它会导致 SEGFAULT,这是一种低级 CPU 错误,通常会导致程序立即中止。

       .psect  rodata
s1     db      '%', 'd', 0
       .psect  code
       mov     eax  s1
       push    eax

在OP的程序中,a是一个"初始化的"全局"。我希望它被放置在数据段的初始化部分。请参阅 https://en.wikipedia.org/wiki/File:Program_memory_layout.pdf,http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.gif(来自有关可执行程序(进程)的内存布局的详细信息)。a的位置由编译器-链接器二人组决定。

另一方面,作为自动(堆栈)变量,堆栈段中预期bc

话虽如此,编译器/链接器可以自由地执行任何优化,只要不违反观察到的行为("假设"规则到底是什么?例如,如果从未引用a,则可以完全优化它。