繁体   English   中英

char数组和指针初始化语义

[英]char array and pointer initialization semantics

在以下代码段中

   char *str1 = "abcd";
   char str2[] = "defg";

我意识到,第一条语句将指向字符串文字的指针存储在可执行文件的只读部分中,而第二条语句将指针存储到读写部分中。 检查生成的指令后,我确认第一个指令在str1的rodata节中存储了指向“ abcd”的指针。

有趣的是第二个陈述。 编译器插入代码以将值存储到

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)

编译器如何决定何时执行以下操作?

  1. 字符串文字存储在rodata节中
  2. 字符串文字存储在数据节(rw)中
  3. 字符串存储器在堆栈中是隐式的,并且生成指令来填充堆栈吗?
  4. 是否还有其他可能性以及硬件之间的差异?

注意:我正在运行带有调试符号和-O0的Precision32 vagrant,gcc

当使用编译时聚合值(不限于字符串文字)初始化内存中的聚合对象时,编译器始终可以选择

  1. 在编译时在只读数据部分中预先构建完整的初始化程序,然后在运行时使用memcpy将整个事情复制到可修改的目标值中。

  2. 生成将在运行时逐段直接构建目标值的代码。

基本上,第一种是“基于数据”的方法,第二种是“基于代码的”方法。 在您的情况下,编译器使用基于代码的解决方案,可能是因为文字简短。 使用更长的文字,我怀疑它将最终切换到第一种方法。

一个可能会想到,在某些情况下,混合方法可能被一些编译器使用:部分数据是预编译的地方,并memcpy -ed分从那里,数据的其余部分是建立在飞。

如果你的

char str2[] = "defg";

定义位于函数内部,然后编译器将生成指令以将数据放入堆栈(忽略可能的优化,例如,将值仅保留在寄存器中)。 就像其他自动(堆栈)变量一样。

它也可以选择将数据从其他地方复制到堆栈,而不是例如将数据值作为指令的立即操作数。 它可能选择对更长的字符串执行此操作,以避免代码膨胀。

无论编译器做什么,都不能在下一次调用该函数时看到对str2内容的修改(就像其他自动变量一样)。

如果str2是全局的(为其提供了静态存储持续时间),则数据将最终位于读/写数据段中。 如果您在函数中为数组提供静态存储持续时间,也会发生这种情况,如下所示:

static char str2[] = "defg";

用字符串文字初始化指针时,如

char *s = "defg";

,数据以只读数据段结尾,并且如何使用数据的地址初始化指针本身的规则与上述相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM