C:所有字符串文字都具有静态存储持续时间吗?

blu*_*ote 5 c arrays initialization string-literals implicit-conversion

我一直在阅读各种来源,字符串文字在程序的整个生命周期中都保留在内存中。在那种情况下,这两个函数之间有什么区别

char *f1() { return "hello"; }
char *f2() {
   char str[] = "hello";
   return str;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果str指向实际的字符串文字(具有静态持续时间),为什么会出现错误?
  • 如果字符串文字被复制到局部变量str,那么原始字符串文字去哪里了?它是否保留在内存中而不引用它?

Joh*_*ger 6

我一直在各种来源中阅读到字符串文字在程序的整个生命周期中都保留在内存中。

是的。

那么,这两个函数有什么区别

char *f1() { return "hello"; }
char *f2() {
   char str[] = "hello";
   return str;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果 str 指向实际的字符串文字(具有静态持续时间),为什么会收到错误?

它不是。事实上,它本身并不指向什么。它是一个数组,而不是一个指针。

  • 如果将字符串文字复制到局部变量 str,则原始字符串文字去了哪里?它是否保留在内存中而不被引用?

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


Vla*_*cow 5

这个

char str[] = "hello";
Run Code Online (Sandbox Code Playgroud)

是由字符串文字初始化的本地数组的声明"hello"

实际上,这与您通过以下方式声明数组相同

char str[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
Run Code Online (Sandbox Code Playgroud)

即数组自己的内存区域(具有自动存储持续时间)由字符串文字初始化。

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

这就是功能

char *f2() {
   char str[] = "hello";
   return str;
}
Run Code Online (Sandbox Code Playgroud)

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

至于这个函数定义

char *f1() { return "hello"; }
Run Code Online (Sandbox Code Playgroud)

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

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

char literal[] = "hello";
char *f1() { return literal; }
Run Code Online (Sandbox Code Playgroud)

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

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

如果 str 指向实际的字符串文字(具有静态持续时间),为什么会出现错误?

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

在返回语句中

return str;
Run Code Online (Sandbox Code Playgroud)

数组被隐式转换为指向其第一个类型元素的指针char *

C 和 C++ 中的函数可能不返回数组。在 C++ 中,函数可以返回对数组的引用。