在下面的代码片段中
char *str1 = "abcd";
char str2[] = "defg";
我意识到第一条语句将指向字符串文字的指针存储在可执行文件的只读部分中,而第二条语句将指针存储在读写部分中。 在检查生成的指令时,我验证第一个指令将 rodata 部分中指向“abcd”的指针存储到 str1。
有趣的是第二个陈述。编译器插入代码以将值存储到
char *str1 = "abcd";
8048420: c7 44 24 10 20 85 04 movl $0x8048520,0x10(%esp)
8048427: 08
char str2[] = "defg";
8048428: c7 44 24 17 64 65 66 movl $0x67666564,0x17(%esp)
804842f: 67
8048430: c6 44 24 1b 00 movb $0x0,0x1b(%esp)
编译器如何决定何时执行以下操作?
- 字符串文字存储在rodata部分
- 字符串文字存储在数据段(rw)
- 字符串内存隐含在栈中,生成指令填充栈?
- 硬件之间是否还有其他可能性和变化?
注意:我正在运行一个 precise32 vagrant,带有调试符号和 -O0 的 gcc
最佳答案
如果你的
char str2[] = "defg";
定义在函数内部,然后编译器将生成指令将数据放入堆栈(忽略可能的优化,例如将值纯粹保存在寄存器中)。这与其他自动(堆栈)变量一样有效。
它也可以选择将数据从其他地方复制到堆栈而不是例如将数据值作为指令的直接操作数。它可能会选择对较长的字符串执行此操作以避免代码膨胀。
无论编译器做什么,对 str2
内容的修改必须在下一次调用该函数时不可见(就像其他自动变量一样)。
如果 str2
是全局的(这给了它静态存储持续时间),那么数据将在读/写数据段中结束。如果您在函数内给数组静态存储持续时间,也会发生这种情况,如
static char str2[] = "defg";
当用字符串文字初始化指针时,如
char *s = "defg";
,数据在只读数据段结束,指针本身如何用数据的地址初始化的规则是一样的以上。
关于char 数组和指针初始化语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29184100/