常量数据存储在哪里
Where is const data stored?
例如:
在文件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
的位置由编译器-链接器二人组决定。
另一方面,作为自动(堆栈)变量,堆栈段中预期b
和c
。
话虽如此,编译器/链接器可以自由地执行任何优化,只要不违反观察到的行为("假设"规则到底是什么?例如,如果从未引用a
,则可以完全优化它。
- 谷歌测试中的期望值存储在哪里
- 常量参数存储在哪里 (C++)?
- 此递归函数的每次迭代的值存储在哪里?
- 如何告诉本机节点模块所需的dll存储在哪里?
- 在哪里存储跨平台C++应用存储?
- 模板参数在 C++ 中存储在哪里?
- 存储在 C++ 编译器中的标识符的定义(不是声明)在哪里?
- 变量或标识符存储在C++中究竟在哪里?
- C++ - thread_local变量存储在哪里?
- 返回值存储在哪里?
- Cmake忽略了我所有关于在boost::beast存储库中在哪里找到提升的指令
- glVertexAttribDivisor 存储在哪里 - VAO、VBO 或全局状态?
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 为什么类型转换对象不会更改其地址?有关对象类型的信息存储在哪里?
- 如果不在内存中,则在哪里存储表达式和常数
- C 在哪里存储固定大小数组的大小
- 在哪里存储Visitor模式中访问的每个元素的计算结果
- winsock在哪里存储套接字的ip地址?
- 在哪里存储用于OSX部署的Qt导入
- PST 文件中的日历邮件在哪里存储约会时间和日期