【问题标题】:I cannot return pointer to local variable, but I can return pointer to data of local struct in c?我不能返回指向局部变量的指针,但我可以返回指向 c 中局部结构数据的指针?
【发布时间】:2021-04-12 18:10:50
【问题描述】:

我知道返回指向局部变量的指针不是一个好主意,因为用于该变量的堆栈将被重用。因此:

#include <stdio.h>

int *func(){
    int x = 10;
    return &x;
}

int main(){
    printf("%p\n",(void*)func());
}

按预期打印(nil)

但是,为什么我可以返回指向本地结构数据的指针? :

#include <stdio.h>

struct foo{
    char c;
    int *p;
};

int *func(){
    struct foo f;
    f.c = 'c';
    
    int local = 10;
    f.p = &local;
    return f.p;
}

int main(){
    int *b = func();
    printf("%d\n",*b);
}

struct foo f 是函数func 中的local,因此每个局部变量都应该有相同的规则——即自动存储在堆栈中。我还没有查看它的汇编程序输出来确认这一点,但如果这个假设不成立,那么为什么要对结构类型进行特殊处理呢?在我看asm之前,struct foo的存储是否在堆栈中?

【问题讨论】:

  • 不是不能返回指针。您可以返回指针。但是如果你使用指针,你可能会发现它不再指向相同的数据。
  • 我不知道为什么你的第一个代码返回 null。这可能是因为编译器优化。尝试编译-O0,然后它可能不会打印nil。
  • print '(nil)' as expected 这是错误的期望。行为是未定义的,任何事情都可以发生。 gcc chooses to return NULL 在这种情况下,但这不是您可以或不应该依赖的东西。第二个例子也是undefined behavior,所以没有必要去思考为什么某事会发生或不发生,因为任何事情都是允许发生的。
  • 这是未定义的行为,任何事情都可能发生,包括看似允许的事情。
  • @milanHrabos 是否简单地打印值是否是 UB,最好留给真正的语言律师来讨论。但无论如何,指针的是未定义的,它可以是任何东西,所以“期望”任何特定的值都是错误的期望。

标签: c struct stack local-storage


【解决方案1】:

你所有的例子都导致undefined behaviour。不再存在的对象的地址是一个不确定的值 (C11 6.2.4/2),尝试打印一个不确定的值会导致未定义的行为。

请参阅this question 了解更多关于使用不确定值和语言规则基本原理的标准参考和讨论。

作为未定义的行为,您不应期待任何特定的行为,例如 nil 或其他。

【讨论】:

  • 那为什么。在第二个示例中,我得到了 10 的完全有效结果(取消引用返回的指针后)?如果那将是空指针,则 UB 将是,但事实并非如此。空指针only在第一个例子中
  • @milanHrabos 输出 10 可能是未定义行为的表现。请阅读我的答案中的链接以了解“未定义行为”的含义。
  • UB 的表现会是如果它不是 10
  • @milanHrabos 不正确。 UB 表示 undefined 行为,而不是“与我的预期行为完全不同”
  • 打印一个不确定的值不会导致未定义的行为。您引用的问题是指使用未获取其地址的自动存储持续时间的未初始化对象(确实具有不确定值)的值。这确实有未定义的行为,但它不适用于此处。
猜你喜欢
  • 2020-10-13
  • 2016-10-25
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 2023-04-09
  • 2013-10-03
相关资源
最近更新 更多