【问题标题】:Undefined variable and the compiler optimization未定义变量和编译器优化
【发布时间】:2020-12-05 04:27:21
【问题描述】:

我有一个关于未定义变量和下面演示的代码片段的问题:

func_1() 之后——它会将A 压入堆栈并将该内存的值设置为40,然后将A 从堆栈中弹出。

func_2()之后——会再次将A压入栈中,并继承之前设置的值,打印出来的值为40。

void func_1()
{ int A = 40;}

void func_2()
{ int A; printf("%d/n",A);}

void main (void)
{
  func_1();
  func_2();
}

如果我们将func_2()中的名称A改成B来测试栈的使用,并在里面添加额外的代码来测试命名变量池的使用:

int A; printf("%d\n", A);

在我的电脑上,B 是 40,A 是 0。

我想知道的是,如果编译器有一个命名变量池,它可以重用以帮助优化编译的代码(?),那么为什么我在A 上得到一个 0? 编译器什么时候使用池?

我的问题基于这张幻灯片: http://www.slideshare.net/olvemaudal/deep-c/131-I_am_now_going_to

【问题讨论】:

    标签: c compiler-construction undefined


    【解决方案1】:

    函数func_2(); 中的变量A 很可能分配在与值40 相同的堆栈位置(在func_1() 中)。由于您尚未在 func_2() 中初始化变量,因此它将使用内存中的随机值打印变量,在这种情况下为 40(因为它从未被覆盖)。它类似于用户释放指针然后声称他们之后也能够看到其内容的场景,尽管他们可能会或可能不会看到该行为被认为是未定义的值。不用说,您不应该依赖这种行为!

    我做了一个简单的测试,证明它与变量名无关:

    void func_1()
    { 
        int A = 40; 
        int B = 10;
        printf("Memory A = %p Memory B = %p\n",&A, &B);
    }
    
    void func_2()
    { int B; printf("B = %d Memory B = %p\n",B, &B);}
    
    void main (void)
    {
      func_1();
      
      func_2();
      printf("\n");
    }
    

    输出

    Memory A = 0x7fff58f86b5c Memory B = 0x7fff58f86b58
    B = 40 Memory B = 0x7fff58f86b5c
    

    如您所见,尽管B = 10func_1()func_2() 中的打印值为40。为什么?如果检查func_1()中的变量A的内存地址是0x7fff58f86b5cfunc_2()中的变量B占用的内存地址相同。

    【讨论】:

      【解决方案2】:

      幻灯片中的角色扮演一个白痴的角色,他发明了一个似乎可以解释他不理解的行为的想法。没有命名变量池。

      这段代码的行为是未定义的,不能依赖。如果它恰好在运行时表现出打印值 40,那只是实现的一个意外。

      【讨论】:

        猜你喜欢
        • 2011-05-06
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-16
        • 1970-01-01
        相关资源
        最近更新 更多