如果用指针引用常量字符串,内存是否永久占用?

1 c malloc pointers

我正在尝试在运行ac程序时了解内存中存储的内容(堆栈/堆,还有其他吗?).编译它会发出警告:函数返回局部变量的地址:

char *giveString (void)
{
    char string[] = "Test";
    return string;
}
int main (void)
{
    char *string = giveString ();
    printf ("%s\n", string);
}
Run Code Online (Sandbox Code Playgroud)

跑步给出了各种结果,它只是打印乱码.我从中收集到,在giveString()中调用字符串的char数组在运行时存储在giveString()函数的堆栈帧中.但是,如果我将giveString()中的字符串类型从char数组更改为char指针:

char *string = "Test";
Run Code Online (Sandbox Code Playgroud)

我没有收到警告,程序打印出"测试".那么这是否意味着字符串"Test"现在位于堆上?它当然不会出现在giveString()的堆栈框架中.这两种情况究竟发生了什么?如果这个字符串位于堆上,那么程序的所有部分都可以通过指针访问它,它会在程序终止之前永远不会被释放吗?或者如果没有指向它的指针就会释放内存空间,就好像我没有将指针返回到main?(但这只能用Java中的垃圾收集器来实现,对吧?)这是堆分配的一个特例,它只适用于指向常量字符串(硬编码字符串)的指针吗?

Var*_*der 6

您似乎对以下语句的作用感到困惑.

char string[] = "Test";
Run Code Online (Sandbox Code Playgroud)

此代码表示:在足够大小的本地堆栈帧中创建一个数组,并将常量字符串"Test"的内容复制到其中.

char *string = "Test";
Run Code Online (Sandbox Code Playgroud)

此代码表示:将指针设置为指向常量字符串"Test".

在这两种情况下,"测试"都位于二进制文件constcstring段中,其中存在不可修改的数据.它既不在堆中也不在堆栈中.在前一种情况下,您正在制作一个可以修改的"测试"副本,但是一旦您的函数返回该副本就会消失.在后一种情况下,您只是指向它,因此您可以在函数返回后使用它,但您永远不能修改它.

您可以将实际字符串"Test"视为全局字符串并始终存在于内存中,但分配和释放的概念通常不适用于const数据.