查询C中的激活记录

时间:2010-06-22 20:37:59

标签: c

以下是我不明白的代码。

#include<stdio.h>

int main(int argc, char *argv[])
{
      int num;

      printf("\n Number: " );
      scanf("%d", &num);

      if (num >= 0)
      {
           int abs = num;
      }
      else
      {
            int abs = -num;
      }

      {
          int abs;
          printf("\n Values are %d %d", num ,abs);
       }
      return 0;
}

当我输入数字4时,输出为Values are 4 4
当我输入一个数字为-4时,输出为Values are -4 4

我无法理解它是如何打印绝对值的?在if循环和else循环中定义的变量abs应该在退出后被解除分配。

请告诉我。

此致 darkie

5 个答案:

答案 0 :(得分:6)

你是完全正确的。

您是否看到上一次宣布int abs的最后一个区块?请注意,abs未初始化,使用未初始化的变量会产生未定义的结果。使用您的特定编译器,只是你运气好了,新的abs所在的内存块仍包含来自它(过期的)前一个范围的结果。

答案 1 :(得分:1)

这些变量是在堆栈上分配但你没有修改它,我的意思是你没有退出这个函数,所以,编程上你会在最后一个代码中得到一个“new”'abs'int块,但实际上,这个“新”'abs'int位于旧'abs'所在的位置(在STACK上!),因此,它的默认值是相同的。

答案 2 :(得分:1)

这被称为“未定义的行为”。

当您使用abs声明printf时,您会收到“堆栈垃圾”。

它的工作原理如下:

if (num >= 0) {
  create 'abs' at memory address N, put 'num' in it.
  destroy 'abs' // but leave the 'garbage' at memory address N
} else {
  create 'abs' at memory address N, put '-num' in it.
  destroy 'abs' // but leave the 'garbage' at memory address N
}

{
  create 'abs' at memory address N, don't put anything in it.
  // your compiler has decided it will reuse N.  That's a valid choice.
  // your compiler has decided it will not zero the memory at address N.  That's valid.
  read whatever was at 'abs'.  // it's whatever was assigned in the conditional.
}

始终使用-Wall编译:)

答案 3 :(得分:0)

你在printf中使用了未初始化的abs值。 C语言标准并不要求它特别是因为它没有初始化。它可以是0,或1,或-32765

在这种特殊情况下,你可能得到相同的数字,因为编译的代码重复使用寄存器来获取abs的临时值,并且再次为printf块中的abs变量注册。

您可以查看反汇编代码,以确切了解编译器在机器指令方面的作用。

答案 4 :(得分:0)

热闹的代码。

由于编译器的优化,它依赖于abs的所有三个定义都将分配在堆栈的同一位置这一事实。

第三个abs必须是随机的garbag,垃圾原来是前一个变量同名的结果(名字无所谓)。