以下代码的输出是什么?

时间:2010-10-01 14:07:24

标签: c

int main()
{
  int x=5,y=10,z=15;
  printf("%d %d %d");
  return 0;
}

输出:15 10 5 //在Turbo C 4.5中

    3 Garbage values in gcc compiler

当我们定义变量时,我的老师告诉我,如int x = 5,y = 10,z = 15;默认情况下,它们被视为自动类型并存储在堆栈中。当您尝试打印3个整数值而不使用printf()的名称时,它将以Turbo C编译器的形式打印这3个LIFO格式的值。 但是我认为当我们定义3个整数变量时,它们可能不会存储在连续的内存位置。所以当我尝试打印3个整数值而不使用它们的名称时,编译器将从堆栈顶部打印任意三个值。所以输出将有3个垃圾值,如gcc ..

6 个答案:

答案 0 :(得分:10)

此代码只显示 Turbo C 在优化代码方面很差,并且将所有内容放在堆栈中,而 gcc 更具攻击性并将其保留在寄存器中或将其丢弃因为这三个变量没有任何目的,所以我们在一起。

无论如何,使用需要三个参数而不提供这些参数的模式调用 printf 是错误的。

<强>更新

作为解释:我假设 printf()将始终从堆栈中获取其参数,因为它是具有可变参数列表的函数。或者是否有人知道 printf()等函数的任何其他调用约定?此外,我假设没有必要在堆栈上放任何其他东西,因为没有其他变量。因此,错误调用 printf 会在 main()中打印堆栈顶部的任何内容。但是可能还有其他架构和调用惯例我的假设不成立。

答案 1 :(得分:4)

这是未定义的行为。

使用优化编译器,可以优化这3个值,因为它们未被使用。它会打印垃圾。

答案 2 :(得分:3)

行为未定义,这意味着编译器可以以任何合适的方式自由处理这种情况。就语言标准而言,Turbo C和gcc都在做“正确”的事情。

答案 3 :(得分:2)

如果格式的参数不足,则行为未定义。

答案 4 :(得分:1)

你的老师错了,但并不完全。

在函数中声明的变量默认为auto而不是static

int foo(void) {
    static int x;
    int y;
    auto int z;

    /* ...other code... */
}

这意味着在y上面的函数是auto,就像z一样,即使auto关键字未在其声明中使用。顺便说一句,auto关键字几乎从未使用过。许多C(和C衍生语言)程序员甚至不知道auto是一个关键字,因为它很少被使用。

作为auto变量通常意味着变量存储在程序的系统堆栈或寄存器或其中的某些组合中。它可以在函数执行过程中的不同时间处于不同的位置,并且当调用另一个函数时,寄存器中的局部变量通常被推送到堆栈。一些局部变量甚至可以被优化掉,这意味着在某些时候编译器能够确定不再需要特定变量的未来值来满足未来代码的输入需求(或者变量不会改变及其值只是在指令内编码)。这使得在优化代码上使用调试器变得复杂。

当您获取局部变量的地址时,编译器会尝试将其锁定到特定地址(可能将其存储在堆栈中)。

当大多数编译器查看您的代码时,他们会看到这些局部变量的名称在声明后未被使用,并且可能决定不将它们的值存储在任何地方。即使它确实将这些值存储在堆栈上,它也可以在设置调用printf之前推送堆栈上的其他值。正如编译器不必保留您在其周围命名的变量一样,也可以自由创建它自己的临时变量。

答案 5 :(得分:0)

在MingW-GCC中:3个垃圾值。

在VC ++ 2010中:0,0和垃圾值。