文字字符串放在哪里,为什么我可以返回它们的指针?

时间:2012-06-16 03:19:34

标签: c string constants literals placement

我在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");

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

3 个答案:

答案 0 :(得分:6)

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

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

,但在带有字符串文字的版本中,字符串的存储可能与其他字符串文字的存储重叠。

答案 1 :(得分: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部分(“ r ead- o nly data”)中,而不是存储在堆栈中,因此它具有“全球”地址(并且始终在范围内)。

同样,myfunc("thisisastring")中的字符串文字也放在.rodata部分中,而不在堆栈中。

答案 2 :(得分:1)

它因ABI而异,但在x86上,它们位于静态存储器/ DATA页面中,由DS寄存器指向。