c - C 中函数返回局部变量地址时的 NULL 行为

标签 c string pointers memory

我有以下 C 代码:

#include <stdlib.h>
#include <stdio.h>

char* foo() {
    char abc[4] = "abc";
    return abc;
}

int main() {
    printf("%s", foo());
    return 0;
}

如果我用 gcc 编译它并运行可执行文件,我会得到 (null)% 作为输出。

如果我运行稍微修改过的代码:

#include <stdlib.h>
#include <stdio.h>

char* foo() {
    char abc[4] = "abc";
    return abc;
}

int main() {
    printf("%c", *(foo()));
    return 0;
}

我遇到了段错误。

我的问题是:为什么我的第一个代码不会出现段错误?我正在运行Linux和gcc版本:gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

这两个代码在编译时都会生成一个警告:函数返回局部变量的地址[-Wreturn-local-addr]警告

最佳答案

return abc;开始执行时,abc是一个指向foo内部定义的数组的指针。 (正式地,它指定数组本身,但它会自动转换为第一个元素的地址。)该函数将返回此指针值。但是,当函数执行结束时,数组的生命周期也结束。

根据 C 2018 6.2.4 2:

The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

当 C 中的值不确定时,它的行为可能就像具有任何值一样,包括每次尝试使用它时都具有不同的值或具有陷阱值 (C 2018 3.19. 2和3.19.3)。请注意,这不仅意味着指针值指向的内容是不确定的;还意味着指针值指向的内容是不确定的。 指针本身的值是不确定的。

因此,即使 abc 在内存中有某个地址(例如 100400),也不意味着 100400 返回给调用者。返回给调用者的是不确定的:它可以是任何值,包括空指针值。

编译器的优化器似乎已通过提供或允许空指针值作为函数 foo 的返回值来响应代码中未定义的行为。这是 C 标准所允许的。

当您将此空指针传递给 printf 以便与 %s 一起使用时,您的 printf 实现检查了该指针,发现它是一个空值指针,并打印“(null)”,而不是尝试使用它来访问内存中的字符串。

当您尝试使用*(foo())取消引用指针时,没有对指针值进行初步检查。程序的机器代码尝试使用空指针访问内存,这导致了段错误。

关于c - C 中函数返回局部变量地址时的 NULL 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63861706/

相关文章:

c - SIGSEGV 同时将 1 位图像数据转换为 8 位

c - 如何从格式打印固定长度的输出

c - 想要使用 if 条件分配 char 值 - C 语言

python - 如何清理 pandas dataframe 中的图像网址?

python - 如果这个字符串有 "and ' ,我该如何读取它? Python

c++ - 在栈尾分配的递归函数

c - 调试了4个小时,还是找不到BUG

C拆分字符串函数

c++ - 如何在 C++ 中使用带有指向对象的指针 vector 的查找算法?

C链表指针理解