3

您好请考虑以下在 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

这里全局变量从数据段移动到文本段。

为什么它从数据移动到文本段?

既然数据段分为读区和读写区,那应该是存放在读区的数据吧?

在代码中间初始化的未初始化全局变量会发生什么?

4

3 回答 3

12

在现代系统上,常量位于对象文件的一部分中,为只读数据保留。该部分在默认模式下通过命令与“文本”(程序代码)部分混为一谈size,但您可以让它为您提供更多详细信息:

$ 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而不是:.textobjdump

$ objdump -t test.o | grep -w global
0000000000000000 g     O .rodata    0000000000000004 global

(“g”代表全局,“O”代表“对象”,而“F”代表函数。)

于 2012-10-20T23:33:08.073 回答
2

文本段是只读的,因此通过将常量放在文本段中,编译器可以确保它是真正的常量。它必须存储在某个地方,因为它被声明为其他目标文件可以访问,因此选择是数据和文本段。

如果它是一个静态变量,编译器可能会消除它,因为它未被使用,无论是否为常量。如果它是静态且恒定的,编译器可能会消除它,以便在它生成的代码中使用它的值。

于 2012-10-20T23:17:28.557 回答
0

我要回到我以前的编辑。我相信,因为它永远不能改变它只是一个编译器优化,因为它们不能改变,所以根本不将常量存储在数据段中。

于 2012-10-20T23:03:43.863 回答