在代码中
char *fun()
{
char *p = "ram";
return p; //char* is local, even though in main it gets printed. why?
}
变量p
是函数的局部变量,它的生命周期以函数结束。但是,您返回的是p
's value,而不是它的地址,所以这并不重要。
p
的值是字符串文字的地址"ram"
。字符串文字的存储方式使得它们在整个程序的生命周期内都可用,从启动到终止 - 文字在退出"ram"
时不会停止存在fun
,因此它的地址保持有效。
为什么下面不起作用?当我从 char *p = "ram" 更改为 char p[]="ram" 时?
现在您已经更改了字符串的存储方式和位置。它不再是存储字符串文字地址的指针,而是p
存储字符串本身内容的数组。字符串的生命周期现在与函数的生命周期相同,因此一旦函数退出,存储该字符串的数组就不再存在并且返回值无效。
我拿了你的代码并添加了一个实用程序1来显示内存中各种项目的地址和内容。首先我们从p
指针的第一个版本开始:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char *p = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
这是输出:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 a0 1a 45 e2 ..E.
0x7ffee2451a44 fe 7f 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee24519b8 04 ef 7a 0d ..z.
0x7ffee24519bc 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee2451a40 04 ef 7a 0d ..z.
0x7ffee2451a44 01 00 00 00 ....
"ram" 0x10d7aef04 72 61 6d 00 ram.
首先,请注意字符串文字在和"ram"
中具有相同的地址。同样,分配字符串文字,以便它们在程序的整个生命周期内都可用。您会注意到它的地址远低于其他项目,这表明它位于非常不同的内存区域中。fun
main
再次注意,p
它只存储字符串的地址,而不是其内容。因此,即使p
不复存在,它的价值仍然有效。
现在,我们更改该代码,使其p
成为数组,而不是指针:
#include <stdio.h>
#include "dumper.h"
char *fun( void )
{
char p[] = "ram";
char *names[] = { "p", "\"ram\"" };
void *addrs[] = { &p, "ram" };
size_t sizes[] = { sizeof p, sizeof "ram" };
puts( "In fun: ");
dumper( names, addrs, sizes, 2, stdout );
return p;
}
int main( void )
{
char *x;
char *names[] = { "x", "\"ram\"" };
void *addrs[] = { &x, "ram" };
size_t sizes[] = { sizeof x, sizeof "ram" };
puts( "Before call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
x = fun();
puts( "After call to fun:" );
dumper( names, addrs, sizes, 2, stdout );
return 0;
}
现在我们的输出如下所示:
Before call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 98 ea 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
In fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
p 0x7ffee059e9bc 72 61 6d 00 ram.
"ram" 0x10f661efc 72 61 6d 00 ram.
After call to fun:
Item Address 00 01 02 03
---- ------- -- -- -- --
x 0x7ffee059ea40 bc e9 59 e0 ..Y.
0x7ffee059ea44 fe 7f 00 00 ....
"ram" 0x10f661efc 72 61 6d 00 ram.
p
现在存储字符串本身的内容,而不是存储字符串文字的地址。一旦fun
退出,p
(以及它所包含的字符串)将不复存在。
- 可在此处获得