【问题标题】:C - Returning a local pointer vs local variableC - 返回本地指针与本地变量
【发布时间】:2017-06-19 12:50:17
【问题描述】:

我的问题是关于这两种情况:

#include <stdio.h>
int *foo1();
int *foo2();

int main()
{
   printf("so it's %d\n",*foo1());
   printf("so it's %d\n",*foo2());
}

int *foo1()
{
   int i1 = 5;
   return &i1;
}

int *foo2()
{
   int i2 = 5;
   int *p = NULL;
   p = &i2;
   return p;
}

case1: 当它是 foo1() 的情况下,我们得到一个错误,因为我们试图将地址的副本返回给 main 其数据已被删除(当我们退出 foo1() 函数时)

case2: 但是在 foo2() 中,它不会给出错误,尽管我们正在返回一个指向局部变量指针的副本,该指针的数据将在之后被删除我们退出 foo2() 函数,为什么会这样?

TL;DR:为什么 foo2() 没有给出错误,但 foo1() 给出了?

TIA。

【问题讨论】:

  • C 还是 C++?还有,g++,gives a warning for both
  • 我相信这与 foo1 返回一个右值而 foo2 返回一个左值这一事实有关,这是一个有效的返回即使指针地址本身无效。
  • 为什么是双标签?
  • @Olaf:当然。从 K&R 开始,做示例练习。
  • @valacmur98 “虽然它是未定义的,但它没有给出错误,所以我想澄清一下”。如果 C 指定了一个错误,那将是定义行为。未定义的行为意味着不需要错误。你可能得到一个,你可能不会。

标签: c pointers memory-management function-pointers


【解决方案1】:

在 C 和 C++ 中,foo1foo2 两个函数的行为未定义

您不能取消引用指向具有自动存储持续时间且不再在范围内的变量的指针。

明天,foo2() 很可能也会给你一个错误。否则编译器可能会吃掉你的猫。

【讨论】:

  • 有用的答案——我总是三重检查我的代码,以确保我的猫不会被编译器吃掉。
  • 我们绝对应该避免导致编译器吃猫的编码实践! :O
  • 我确信“编译器”不能吃掉你的猫。运行时生成的代码虽然可以。
  • @AjayBrahmakshatriya:你能指出 C 标准中的任何地方来支持你的主张吗?我认为编译器可以同时吃掉程序和猫。
  • 编译器没有通过编译具有未定义行为的代码来执行未定义行为。编译any程序是为编译器定义的。
【解决方案2】:

在这两种情况下,您都是通过返回指向局部变量的指针并取消引用来调用 undefined behavior

调用未定义的行为并不意味着您总是会崩溃。这意味着程序的行为是未定义的。它可能会崩溃,它可能会输出奇怪的结果,或者它可能看起来工作正常。如您所见,这种行为在您的程序中以其中两种方式表现出来。

进行看似无关的更改,例如添加未使用的局部变量或printf 进行调试,可以改变未定义行为的表现方式。

【讨论】:

    【解决方案3】:

    两者都是未定义的行为,您不能依赖编译器为您提供未定义行为的警告。

    您在这两个函数中本质上是在做同样的事情,实际上两者都可能导致生成相同的汇编代码。

    【讨论】:

      【解决方案4】:

      case1 和 case2 的行为都是未定义的,不能返回指向局部变量的指针

      【讨论】:

        猜你喜欢
        • 2014-08-02
        • 1970-01-01
        • 2014-05-14
        • 2010-12-01
        • 2018-09-13
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多