C:是否所有的字符串文字都有静态存储期限?

C: do all string literals have static storage duration?

我在各种资源中了解到,字符串文字在程序的整个生命周期内都保留在内存中。在那种情况下,这两个函数有什么区别

char *f1() { return "hello"; }
char *f2() {
   char str[] = "hello";
   return str;
}

虽然 f1 编译正常,但 f2 抱怨我正在返回堆栈分配的数据。这里发生了什么?

这个

char str[] = "hello";

是由字符串文字 "hello".

初始化的局部数组的声明

实际上这和你用下面的方式声明数组是一样的

char str[] = { 'h', 'e', 'l', 'l', 'o', '[=11=]' };

也就是数组自己的内存区域(自动存储时长)用字符串字面量初始化

退出函数后数组将不存在。

就是这个函数

char *f2() {
   char str[] = "hello";
   return str;
}

尝试return指向具有自动存储持续时间的本地字符数组str的第一个元素的指针。

至于这个函数定义

char *f1() { return "hello"; }

然后函数 return 指向确实具有静态存储持续时间的字符串文字 "hello" 的第一个字符。

你可以想象第一个函数定义如下

char literal[] = "hello";
char *f1() { return literal; }

现在比较第一个函数定义和第二个函数定义中数组的定义位置。

在第一个函数定义中,数组 literal 是全局定义的,而在第二个函数定义中,数组 str 是局部定义的。

if the str points to the actual string literal (which has static duration), why do I get an error?

str 不是指针。它是由字符串文字初始化的命名内存范围。即数组的类型为 char[6].

在return语句中

return str;

数组被隐式转换为指向其类型 char *.

的第一个元素的指针

C 和 C++ 中的函数可能不是 return 数组。在 C++ 函数中,可以 return 引用数组。

I've been reading in various sources that string literals remain in memory for the whole lifetime of the program.

是的。

In that case, what is the difference between those two functions

char *f1() { return "hello"; }
char *f2() {
   char str[] = "hello";
   return str;
}

f1 returns 指向由字符串文字表示的数组第一个元素的指针,它具有静态存储持续时间。 f2 returns 指向 自动 数组 str 的第一个元素的指针。 str 有一个用于初始值设定项的字符串文字,但它是一个单独的对象。

While f1 compiles fine, f2 complains that I'm returning stack allocated data. What happens here?

  • if the str points to the actual string literal (which has static duration), why do I get an error?

没有。事实上,它本身并没有指向任何东西。是数组,不是指针。

  • if the string literal is copied to the local variable str, where does the original string literal go? does it remain in memory with no reference to it?

C 没有指定,但实际上,是的,字符串文字的某些表示必须存储在程序中的某个位置,也许在函数实现中,因为它需要用于重新初始化 str每次调用 f2

char str[] = "hello"; 是一种复制字符串文字的特殊语法,您的函数 returns 是指向此局部变量的指针,一旦函数 returns.[=15 就被销毁=] char *f1() { return "hello"; } 是正确的,但返回 const char* 可能会更好。

您将在堆栈中看到的字符串不是字符串文字存在的直接结果。在 ELF 的情况下,字符串与链接器在链接过程中遇到的其他字符串文字一起存储在名为 "string table section" 的 executable 二进制文件的单独区域中。每当实际导致字符串被包含的代码的堆栈上下文被实例化时,字符串 table 部分中的字符串内容实际上被 复制到堆栈 .

您可能感兴趣的简要阅读: http://refspecs.linuxbase.org/elf/gabi4+/ch4.strtab.html