const char *p = "some_string" 和 const char[] = "some_string" 在内存分配方面的区别

时间:2021-01-10 15:45:56

标签: c++ c c-strings

const char *fun1()
{
    const char *a = "hello";
    return a;
}

const char *fun2()
{
    const char a[] = "hello";
    return a;
}

int main(int argc, char *argv[])
{
    printf("%s\n", fun1());
    printf("%s\n", fun2());
    return 0;
}

输出:

cpp:12:12: warning: address of local variable 'a' returned [-Wreturn-local-addr]
   12 |     return a;
      |            ^
passwords.cpp:11:16: note: declared here
   11 |     const char a[] = "hello";
      |                ^
hello
(null)

这两种分配字符串的方法有什么区别? 我收到一个警告而另一个没有? 我知道当我们从函数返回时局部变量会被破坏,但为什么 fun1() 不是这种情况? 它是否在其他地方而不是堆栈中获得内存?

1 个答案:

答案 0 :(得分:4)

在您的情况下,fun1() 中字符串的字节存在于静态内存中。在另一个函数中,字节在初始化时从静态内存复制到堆栈上的缓冲区中。访问从fun2()返回的返回字符串是未定义的,因为堆栈上的数组不再存在。

fun1() 可以改写为

const char fun1()
{
    static const char s[] = "hello";
    const char* a = s;
    return a;
}

fun2() 可以改写为

const char fun2()
{
    static const char s[] = "hello";
    const char a[6]; // stack allocation (5 letters + 1 zero terminator)
    strcpy(a, s);
    return a; // UB: return pointer to local automatic array
}

所以你得到警告的主要原因是调用后 fun2() 中的数组不存在。你返回一个指针到栈帧中,同样的方式下面的代码也有同样的问题:

struct S { int x, y; };

struct S* fun1()
{
    static struct S s = { 10, 42 };
    return &s; // no problem
}

struct S* fun2()
{
    struct S a = { 10, 42 };
    return &a; // UB
}
相关问题