常量局部变量数组在内存中用于’C’程序
我正在使用GCC 4.8.1,它似乎没有将const变量本地存储在DATA段中的main。 下面是3个这样的程序的代码和内存映射:
代码1:
int main(void) { //char a[10]="HELLO"; //1 //const char a[10] = "HELLO"; //2 return 0; } MEMORY MAP FOR ABOVE: text data bss dec hex filename 7264 1688 1040 9992 2708 a.exe
代码2:
int main(void) { char a[10]="HELLO"; //const char a[10] = "HELLO"; return 0; } MEMORY MAP FOR 2: text data bss dec hex filename 7280 1688 1040 10008 2718 a.exe
代码3:
int main(void) { //char a[10]="HELLO"; const char a[10] = "HELLO"; return 0; } MEMORY MAP FOR 3 : text data bss dec hex filename 7280 1688 1040 10008 2718 a.exe
我没有看到3个代码之间的数据段有任何差异。 有人可以向我解释这个结果。
在期待中感谢!
这是应该发生的事情:
代码1:任何地方都没有存储。
代码2: a
存储在堆栈中。 它不存储在.data
。
代码3a要么存储在堆栈中,要么存储在.rodata
,具体取决于它是否使用常量表达式进行初始化。 优化器也可能决定将其存储在.text
(与代码一起)。
我没有看到3个代码之间的数据段有任何差异。
那是因为应该没有区别。 .data
用于具有静态存储持续时间的非常量变量,初始化为非零值。
如果程序不使用您的数组,则允许编译器简单地优化对象。
从C标准:
(C99,5.1.2.3p1)“本国际标准中的语义描述描述了抽象机器的行为,其中优化问题无关紧要”
和
(C99,5.1.2.3p3)“在抽象机器中,所有表达式都按语义指定进行评估。实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用而且没有必要的副作用生成(包括通过调用函数或访问volatile对象而导致的任何内容)。“
如果编译程序#3并禁用优化( -O0
)或依赖于编译器,仍然可以分配对象。 在您的情况下,它不会出现在data
和rodata
部分中,而是出现在text
部分中,因此text
部分会增加。
例如,在您的第三个示例中,在我的编译器中,使用-O0
生成的代码(使用objdump -d
转储):
00000000004004d0 : 4004d0: 55 push %rbp 4004d1: 48 89 e5 mov %rsp,%rbp 4004d4: 48 b8 48 45 4c 4c 4f mov $0x4f4c4c4548,%rax 4004db: 00 00 00 4004de: 48 89 45 f0 mov %rax,-0x10(%rbp) 4004e2: 66 c7 45 f8 00 00 movw $0x0,-0x8(%rbp) 4004e8: b8 00 00 00 00 mov $0x0,%eax 4004ed: 5d pop %rbp 4004ee: c3 retq 4004ef: 90 nop
0x4f4c4c4548
是在字符串中移动的字符串的ASCII字符,然后在堆栈中推送。
如果我用-O3
编译相同的程序,输出就是:
00000000004004d0 : 4004d0: 31 c0 xor %eax,%eax 4004d2: c3 retq 4004d3: 90 nop
并且字符串不会出现在data
或rodata
,只是简单地优化了。