简体   繁体   English

以下代码的输出是什么?

[英]What is the output of the following code?

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

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

    3 Garbage values in gcc compiler

My teacher told me when we define the variables like int x=5,y=10,z=15; 当我们定义变量时,我的老师告诉我,如int x = 5,y = 10,z = 15; they are by default taken as auto type and stored in stack.When you try print 3 integer values without using their names by printf(), it will print those 3 values in LIFO format as Turbo C compiler does. 默认情况下,它们被视为自动类型并存储在堆栈中。当您尝试打印3个整数值而不使用printf()的名称时,它将以Turbo C编译器的形式打印这3个LIFO格式的值。 But what I think when we define 3 integer variables, they may not be stored in continuous memory locations.So when I try to print 3 integer values without using their names, the compiler will print any three values from top of the stack.so the output will come 3 garbage values as in gcc.. 但是我认为当我们定义3个整数变量时,它们可能不会存储在连续的内存位置。所以当我尝试打印3个整数值而不使用它们的名称时,编译器将从堆栈顶部打印任意三个值。所以输出将有3个垃圾值,如gcc ..

This code just shows that Turbo C is poor at optimizing code and puts everything on the stack, while gcc is more aggressive and keeps it in registers or throws it away all together because these three variables have no purpose. 这段代码只是表明Turbo C很难优化代码并将所有内容放在堆栈上,而gcc更具侵略性并将其保存在寄存器中或将它们全部抛在一起,因为这三个变量没有任何意义。

Anyway, calling printf with a pattern that requires three arguments without providing these arguments, is a mistake. 无论如何,使用需要三个参数而不提供这些参数的模式调用printf是一个错误。

Update: 更新:

As an explanation: I'm assuming that printf() will always take its argument from the stack since it's a function with a variable argument list. 作为解释:我假设printf()将始终从堆栈中获取其参数,因为它是具有可变参数列表的函数。 Or does anybody know any other calling convention for functions like printf() ? 或者有人知道printf()函数的任何其他调用约定吗? Futhermore, I'm assuming there's no need to put anything else on the stack as there are no other variables. 此外,我假设没有必要在堆栈上放任何其他东西,因为没有其他变量。 So this mistaken call of printf will print whatever is on top of the stack in main() . 所以这个错误的printf调用将打印main()中堆栈顶部的任何内容。 But there might be other architectures and calling conventions where my assumpations don't hold. 但是可能还有其他架构和调用约定我的假设不成立。

This is undefined behavior. 这是未定义的行为。

With an optimizing compiler, these 3 values might be optimized out as they are not used. 使用优化编译器,这三个值可能会在未使用时进行优化。 It will print garbage. 它会打印垃圾。

The behavior is undefined, meaning the compiler is free to handle the situation in any way it sees fit. 行为未定义,这意味着编译器可以以任何合适的方式自由处理该情况。 As far as the language standard is concerned, both Turbo C and gcc are doing the "right" thing. 就语言标准而言,Turbo C和gcc都在做“正确”的事情。

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

Your teacher is wrong, but not entirely. 你的老师错了,但并不完全。

Variables declared within a function are by default auto rather than static . 函数内声明的变量默认为auto而非static

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

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

This means that in the function above y is auto, just like z, even though the auto keyword is not used in its declaration. 这意味着在上面的函数中, y是auto,就像z一样,即使auto声明中没有使用auto关键字。 The auto keyword is almost never used, by the way. 顺便说一句, auto关键字几乎从未使用过。 Many C (and C derivative language) programmers don't even know that auto is a keyword because it is used so infrequently. 许多C(和C衍生语言)程序员甚至不知道auto是一个关键字,因为它很少被使用。

Being an auto variable usually means that the variable is stored on the program's system stack or in registers or some mix of these. 作为auto变量通常意味着变量存储在程序的系统堆栈或寄存器或这些变量的某些组合中。 It can be at different places at different times during the course of execution of the function, and local variables that are in registers are often pushed to the stack when another function is called. 它可以在函数执行过程中的不同时间处于不同的位置,并且当调用另一个函数时,寄存器中的局部变量通常被推送到堆栈。 Some local variables may even be optimized away, meaning that at some point the compiler was able to determine that a particular variable's future value was no longer needed to satisfy the input needs of the future code (or the variable doesn't change and its value is just encoded within instructions). 一些局部变量甚至可以被优化掉,这意味着在某些时候编译器能够确定不再需要特定变量的未来值来满足未来代码的输入需求(或者变量不会改变及其值只是在指令内编码)。 This complicates using debuggers on optimized code. 这使得在优化代码上使用调试器变得复杂。

When you take the address of a local variable the compiler then tries to lock it down to a specific address (probably by storing it on the stack). 当您获取局部变量的地址时,编译器会尝试将其锁定到特定地址(可能通过将其存储在堆栈中)。

When most compilers look at your code they will see that the names of those local variables are not used after their declaration and may decide to just not store their values anywhere. 当大多数编译器查看您的代码时,他们会看到这些局部变量的名称在声明后不会被使用,并且可能决定不将它们的值存储在任何地方。 Even if it does store those values on the stack it may also push other values on the stack before setting up to call printf . 即使它确实将这些值存储在堆栈上,它也可能在设置调用printf之前将其他值推送到堆栈上。 Just as the compiler does not have to keep the variables you named around it is also free to create it's own temporary variables. 正如编译器不必保留您在其周围命名的变量一样,也可以自由地创建它自己的临时变量。

In MingW-GCC: 3 garbage values. 在MingW-GCC:3个垃圾值。

In VC++ 2010: 0, 0, and a garbage value. 在VC ++ 2010中:0,0和垃圾值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM