从函数返回字符串文字真的安全吗?

ale*_*ari 0 c c-strings lifetime string-literals

考虑这段代码:

char *test() {
    return "HELLO";
}

int main() {
    char *p = test();
    printf("%s\n", p);
}
Run Code Online (Sandbox Code Playgroud)

这会在没有警告的情况下进行编译,我猜是因为"HELLO"它没有存储在堆栈中。但这给了我一个警告:

char *test() {
    char arr[] = "HELLO";
    return arr;
}

int main() {
    char *p = test();
    printf("%s\n", p);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. 字符串文字真的存储在称为字符串文字池的区域中吗?

  2. 如果是这样,存储在字符串文字池中的数据是否可以被视为全局数据?

  3. 从函数返回字符串文字总是安全的(因为它是全局的)?

Vla*_*cow 7

字符串文字具有静态存储期限。也就是说它们在程序执行期间是活动的。

您可以考虑第一个功能

char* test(){
    
    return "HELLO";
}
Run Code Online (Sandbox Code Playgroud)

以下方式

char* test(){
    static char arr[] = { 'H', 'E', 'L', 'L', 'O', '\0' };   
    return arr;
}
Run Code Online (Sandbox Code Playgroud)

至于第二个程序

char* test(){
    
    char arr[] = "HELLO";
    return arr;
}
Run Code Online (Sandbox Code Playgroud)

然后返回一个指向arr具有自动存储期限的本地数组的指针,该指针在退出函数后将不存在。因此返回的指针将无效,并且取消引用它会导致未定义的行为。

来自 C 标准(6.2.4 对象的存储持续时间)

3 如果一个对象的标识符是在没有存储类说明符 _Thread_local 的情况下声明的,并且具有外部或内部链接或具有存储类说明符 static,则具有静态存储持续时间。它的生命周期是程序的整个执行过程,并且其存储的值仅在程序启动之前初始化一次。

和(6.4.5 字符串文字)

6 在转换阶段 7 中,将值为零的字节或代码附加到由一个或多个字符串文字产生的每个多字节字符序列。78)然后使用多字节字符序列来初始化静态存储持续时间和长度刚好足够的数组包含序列.