【问题标题】:Where are literal strings placed and why can I return pointers to them?文字字符串放在哪里,为什么我可以返回指向它们的指针?
【发布时间】:2012-06-19 02:29:38
【问题描述】:

我在answerthis question 中偶然发现了这个函数:

/* Note: I've formatted the code for readability. */
const char * getString() {
    const char *x = "abcstring";
    return x;
}

我惊讶地发现返回一个指向文字字符串的指针是有效的,并且没有像我想象的那样发生段错误。我一直认为文字被推入堆栈或放入其他一些临时内存,但仅限于函数的范围。但在这里,它们似乎比我想象的更静态。然后将它们放入对整个可执行文件全局的某种字符串池中吗?

另外,如果我将字符串文字作为参数传递给函数,是否也是同样的事情?例如:

/* Where is the string literal in this example being placed? */
myfunc(value1, value2, "rainbowdash");

我希望有人能启发我。提前致谢! :)

【问题讨论】:

标签: c string constants literals placement


【解决方案1】:

每个 ABI 都不同,但在 x86 上它们位于静态内存/DATA 页面中,由 DS 寄存器指向。

【讨论】:

  • 它们总是在静态存储中。这是 C 语言所要求的。
【解决方案2】:

在 C 中,字符串文字具有静态存储持续时间。您的代码在逻辑上等同于:

const char * getString() {
    static const char literal[] = "abcstring";
    const char *x = literal;
    return x;
}

除了在带有字符串字面量的版本中,字符串的存储可能与其他字符串字面量的存储重叠。

【讨论】:

    【解决方案3】:

    作为大多数其他答案的附录,您可以查看编译器生成的汇编程序(例如,通过将 -S 传递给 GCC)以了解它们的存储方式。将你的函数单独放入一个文件,我们发现GCC基本上会生成(我已经删除了一些不相关的东西):

    .section        .rodata
    .LC0:
            .string "abcstring"
            .text
    
            .globl  getString
            .type   getString, @function
    getString:
            # load the address of ".LC0" which is the start of the "abcstring"
            movl    $.LC0, %eax 
            ret
    

    因此字符串存储在.rodata 部分(“read-only 数据”)中,而不是在堆栈中,因此它具有“全局" 地址(并​​且始终在范围内)。

    同样,myfunc("thisisastring") 中的字符串字面量也被放入 .rodata 部分,并且不在堆栈中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 2021-12-05
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多