【问题标题】:Declare variable in two functions but only initialize one of them [closed]在两个函数中声明变量,但只初始化其中一个[关闭]
【发布时间】:2016-03-16 23:14:09
【问题描述】:

变量 a 在两个单独的函数中声明,但只在其中一个函数中初始化。主函数调用声明和初始化 a 的函数,然后调用第二个函数重新声明该变量而不初始化它。它打印 42,即使 a 在不同的函数范围内初始化,其数据应该在函数完成后被销毁。为什么会这样?

#include <stdio.h>
void foo() {
    int a = 42;
}
void bar() {
    int a;
    printf("%d",a);
}
main() {
    foo();
    bar();
}

【问题讨论】:

  • 他们是不同的as。阅读变量范围
  • 你告诉我们,它打印的是 42 吗?
  • 顺便说一句,它实际上是在两个函数中定义的,但只在一个函数中初始化。它在问题中的措辞倒置
  • 谢谢@TinyTheBrontosaurus
  • 啊,该死。以为这是重复的。结果不完全是,我想到的是c++,但我认为很多相同的原则也适用于此。 Eric Lippert 通常有很好的答案:stackoverflow.com/questions/6441218/…

标签: c scope


【解决方案1】:

官方的回答是这样

void bar() {
    int a;
    printf("%d",a);
}

调用“未定义的行为”。任何事情都可能发生。它可以打印一首诗,格式化你的硬盘,打开白宫圣诞树上的灯,......它甚至可以打印 42 并且有些人会告诉你在某些情况下这是怎么发生的。

在其他地方你有另一个名为a 的变量是无关紧要的

【讨论】:

    【解决方案2】:

    哦,那是一个很好的。官方是未定义的。但我敢打赌,其中很多会打印 42,因为 a 可能会使用堆栈上的相同内存地址。

    因此,其工作原理的基本原理是,当调用函数时,程序应返回的 PC(程序计数器)的值与参数一起被压入堆栈。在这种情况下, foo 和 bar 都没有参数,因此只有一个指针将被压入堆栈(也就是说,从相对地址 0 开始总共有 4 个字节)。

    然后当一个函数启动时,它的变量被压入堆栈。在这种情况下,它们都有一个将被推送的,每个又是 4 个字节(总共 8 个字节,从相对地址 4 开始)。

    这是 C/C++ 中从其他函数/程序中获取数据的常用方法,否则该函数不应被允许访问。

    【讨论】:

    • 我敢打赌,a 会完全从 foo 优化出来。
    【解决方案3】:

    未定义的行为。您正在打印一个未初始化的变量。 foo 中的 a 在概念上与 bar 中的 a 是不同的变量。

    虽然 UB 可以(根据标准)执行@pm100 建议的所有奇怪的事情,但在现实世界中,它会打印出发生在某个随机内存位置或寄存器中的任何内容。所以,一个未定义的值。

    它会打印 42 吗?可能。 a: 因为未定义的值是 42 的随机机会,b: 因为内存/寄存器可能是 foo 用 42 写入的,并且没有被其他东西覆盖。

    我可以依赖它总是打印 42 吗? 100%,不!

    【讨论】:

      【解决方案4】:

      未定义的行为!

      如果优化关闭,观察到的行为是 clang 和 gcc print 42。如果您添加 -O1,则 foo 函数会有效地消失,而 printf 然后会打印一些垃圾。

      下面的程序告诉你a指向的有效地址在两个函数中是一样的

      #include <stdio.h>
      #include <stdint.h>
      void foo();
      void bar();
      
      void foo() {
        uint8_t a = 255;
        uint8_t b = 255;
        printf("%p\n",&a);
      }
      
      void bar() {
        uint16_t a;
        printf("%p\n",&a);
        printf("%hu\n",a);
      }
      int main(void) {
        foo();
        bar();
      }
      

      输出是

      0x7fff54dd259e
      0x7fff54dd259e
      65535
      

      这是今天在这些天气条件下我的机器上观察到的行为。您当然可以观察飞猪、粉红大象或任何形式的Heisenbug,同时尝试观察上述代码的实际作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-09
        • 2013-04-08
        • 1970-01-01
        • 1970-01-01
        • 2013-03-14
        • 2012-06-04
        • 2021-10-28
        相关资源
        最近更新 更多