您好请考虑下面的代码片段在Linux机器(64位)上用gcc编译,并带有相应的内存映射
#include <stdio.h>
int global = 2;
int main(void)
{
int local = 0;
return 0;
}
text data bss dec hex filename
1092 500 16 1608 648 mem
这里因为有一个全局变量初始化为2。它已存储在数据段中 考虑将其设为const如下所示的情况
#include <stdio.h>
int const global = 2;
int main(void)
{
int local = 0;
return 0;
}
text data bss dec hex filename
1096 496 16 1608 648 mem
此处全局变量从数据段移动到文本段。
为什么它会从数据移到文本段?
由于数据段分为读取和读写区域,它应该存储在数据的读取区域中吗?
在代码中间初始化的未初始化的全局变量会发生什么?
答案 0 :(得分:12)
在现代系统中,常量是在为只读数据保留的目标文件的一部分中。该部分在默认模式下通过size
命令与“text”(程序代码)部分混为一谈,但您可以使它为您提供更多详细信息:
$ size test.o # compiled from the code in the question
text data bss dec hex filename
58 0 0 58 3a test.o
$ size -A test.o
test.o :
section size addr
.text 6 0
.data 0 0
.bss 0 0
.rodata 4 0
.comment 29 0
.note.GNU-stack 0 0
.eh_frame 48 0
Total 87
查看第一个命令生成的“文本”编号是第二个问题产生的.text
,.rodata
和.eh_frame
数字的总和?
您可以使用.rodata
命令判断常量是.text
而不是objdump
:
$ objdump -t test.o | grep -w global
0000000000000000 g O .rodata 0000000000000004 global
('g'代表全局,'O'代表'对象'而不是'F'代表函数。)
答案 1 :(得分:1)
文本段是只读的,因此通过将常量放在文本段中,编译器会确保它是真正的常量。它必须存储在某个地方,因为它被声明为可供其他目标文件访问,因此选择是数据和文本段。
如果它是静态变量,编译器可能能够消除它,因为它是未使用的,无论是否为常量。如果它是静态和常量的,编译器可能会将其消除,而不是在其生成的代码中使用它的值。
答案 2 :(得分:0)
我将回到之前的编辑。我相信,因为它永远不会改变它的简单编译器优化而根本不存储数据段中的常量,因为它们无法改变。