Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 返回指向静态变量的本地指针_C_Static - Fatal编程技术网

C 返回指向静态变量的本地指针

C 返回指向静态变量的本地指针,c,static,C,Static,这是密码 char *foo() { static char s[10] = "abcde"; return s; } char *bar() { char *c = foo(); return c; } int main() { printf("%s\n", bar()); } 通常,像我在bar中那样返回本地指针是错误的,但是现在c指向foo返回的staticvar,在bar中返回本地varc是否正确 我试过了,它printf是正确的值,但我不

这是密码

char *foo()
{
    static char s[10] = "abcde";
    return s;
}

char *bar()
{
    char *c = foo();
    return c;
}

int main()
{
    printf("%s\n", bar()); 
}
通常,像我在
bar
中那样返回本地指针是错误的,但是现在
c
指向
foo
返回的
static
var,在
bar
中返回本地var
c
是否正确

我试过了,它
printf
是正确的值,但我不明白它是如何工作的。我想,当
bar()
结束时,var
c
应该消失,这应该使
printf
打印未定义的内容,对吗

跟进


char*c
是一个局部变量,如果
char*c=“abcde”
,我假设:
c
是一个驻留在函数堆栈中的局部变量,而
“abcde”
是一个驻留在常量区域(堆的一部分?)的常量变量,因此当
bar()
完成时,
c
消失,但
“abcde”
仍保留在堆中,对吗?

变量
c
只是一个指针。从函数返回本地指针并没有错,您一直都在这样做。例如,当您在指针中存储
malloc
的结果时,指针是本地的,但它指向的存储不是本地的。但是,返回指向本地存储的指针是错误的。因为在您的示例中
c
从不指向本地分配的数据,所以您的代码可以正确地运行

编辑(响应后续行动)

“abcde”是一个常量变量,它位于常量区域(堆的一部分?)

常量区域通常不是堆的一部分,它是一个单独的arrea,通常与存储程序机器代码的区域相邻

c消失了,但“abcde”仍然在堆中,对吗

“abcde”保留在常量区域中,而不是堆中,但概念是正确的:指向该常量的指针在程序的整个运行期间保持有效。

返回
c
的值,即
foo()
s
abcde
的地址。
bar
返回的是执行
char*c=foo()操作时存储该值的空间


所以,是的,这是正确的。

你的直觉是正确的,但你似乎遇到的问题是:

C中有三种类型的存储

自动(正常的本地存储)位于堆栈上,返回函数后指向此数据的指针不再有效

Dynamic(想想malloc),在调用free()后,它位于堆中,指向该数据的指针不再有效

静态的存在于数据段中(因此不会消失)

由于s是一个静态变量,它将持续整个程序生命周期。所以,不,当富回来时,它不会消失


编辑:我应该补充一点,也有寄存器,但大多数编译器基本上都忽略了这一点。

函数中的静态局部变量将保留在内存中,直到应用程序结束,并且在函数返回时不会消失。这就是为什么在
printf
中,即使在函数
foo
之外,使用指向静态变量的指针也能提供有效数据的原因


如果局部变量不是静态的,那么当函数返回时变量消失时,相同的测试将失败。

Aha,是的。但很抱歉,我想做的只是另一个“后期编辑”。@Alcott我编辑了答案以响应后续操作。顺便说一句,我在哪里可以获得有关常量区域的更多详细信息?从这里开始,然后从这里开始@Alcott是一个快速参考,解释了运行程序的各种内存段。字符常量通常存储在代码段中,尽管这取决于体系结构:有时,在程序启动时,字符常量会复制到数据段。因此,当
c
消失时,“abcde”仍然存在,因此
的地址“abcde”
是有效的,对吧?我想你需要理解函数返回后变量“消失”的含义。看看汇编代码,使用gcc test.c-O0-S编译。
register
不会被忽略。获取
寄存器的地址
变量违反了约束,这正是它现在的目的,告诉编译器如果您获取了这样一个变量的地址,就会收到警告。这是真的。然而,这可能是历史原因造成的。请参见“否”,它只是优化的一个平均值,例如
restrict
关键字。它也避免了你在回答中所说的错误。你不能记下它的地址,所以你永远不会想把它还给打电话的人。如果只是出于历史原因,委员会可能会宣布它从那时起就过时了,这是因为它的一些特性。让我们明确一点,C的全球标准是70年代的ANSI C。当时的计算机,尤其是编译器更为原始。登记处当时有它的位置。至于寄存器的存在是为了防止程序员犯一些愚蠢的错误。首先,这与c语言相反,其次,它只在那里,因为寄存器中的数据不能获取它的地址。此外,C++用户想要贬低它。看,你错了,ANSI C是1989年第一次标准化的,标准化这一方面确实是一个很大的优势。既然你提到标准(而不是市场份额或诸如此类的东西),那么从去年12月开始,C的当前标准是C11。它是由国际标准组织ISO给出的。在这个问题上,它不是像
static char*foo()
而不是
char*foo()
,因为foo的返回类型是
static char*
。它可能会抛出:警告:“foo”[-Wmissing prototype]没有以前的原型。