以下示例来自here
#include<stdio.h>
char** func1_Str();
char** func2_Str();
int main(void)
{
char **ptr1 = NULL;
char **ptr2 = NULL;
ptr1 = func1_Str();
printf("\n [%s] :: func1_Str() address = [%p], its returned address is [%p]\n",*ptr1,(void*)func1_Str,(void*)ptr1);
ptr2 = func2_Str();
printf("\n [%s] :: func2_Str()address = [%p], its returned address is [%p]\n",*ptr2,(void*)func2_Str,(void*)ptr2);
printf("\n [%s] [%p]\n",*ptr1,(void*)ptr1);
return 0;
}
char** func1_Str()
{
char *p = "Linux";
return &p;
}
char** func2_Str()
{
char *p = "Windows";
return &p;
}
输出:
$ ./static
[Linux] :: func1_Str() address = [0x4005d5], its returned address is [0x7fff705e9378]
[Windows] :: func2_Str()address = [0x4005e7], its returned address is [0x7fff705e9378]
[Windows] [0x7fff705e9378]
$
为什么func1_Str()
和func2_Str()
会使用相同的地址初始化char *p
?是否与指针同名的事实有关?
答案 0 :(得分:1)
如果为代码启用了一些警告,一个好的编译器会警告你“正在返回一个局部变量的地址”(或类似的东西)。
char** func1_Str()
{
char *p = "Linux";
return &p;
}
在此示例中,p
位于堆栈上,并使用常量字符串"Linux"
的地址进行初始化。然后,您将在堆栈上返回p
的地址,并在此之后立即重置堆栈指针,此时函数将返回到调用方。然后,当您调用func2_Str
时,堆栈上的相同位置将重新使用p
在func2_Str
。堆栈就像厨房里的一叠盘子,当你打电话给一个功能时,你把新的牌子放上,你在回来时再次关闭。
所以,是的,你会得到两个指针的相同地址,因此,当然,他们指向的任何东西都是一样的。
变量的名称与它无关(如果您尝试将其中一个重命名为其他内容的简单实验,您会发现)。你也可以这样做:
char** func1_Str()
{
char *q = "Windows";
char *p = "Linux";
return &p;
}
你可能(可能)看到p
的值已经改变,因为我们现在需要另外四个字节。
(我也觉得你的系统与链接中的例子完全相同的地址是相当惊人的 - 你实际上是自己编译的,还是只是从网站上复制和粘贴) (当然,如果您实际上已经阅读了您链接的网站上的文字,那么您会理解这一点)
答案 1 :(得分:1)
恰好,func1_Str
和func2_Str
的堆栈内存要求完全相同。因此,p
中func1_Str
使用的内存位置恰好与p
中func2_Str
使用的内存位置一致。