2010-10-01 114 views
4
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编译器的LIFO格式打印这3个值。 但是,当我们定义3个整型变量时,我们认为它们可能不会存储在连续的内存位置中。因此,当我尝试在不使用其名称的情况下打印3个整数值时,编译器将从堆栈顶部打印任何三个值。输出将会出现3个垃圾值,如gcc ..

+0

那么,你的问题是...? – 2010-10-01 14:13:43

+2

找一位新老师。如果他说的不是“这是不确定的行为,不要做”,他不知道他在说什么。 – JeremyP 2010-10-01 14:16:02

+0

@Daniel Standage逻辑上正确的是什么? – Parikshita 2010-10-01 14:19:35

回答

10

此代码只是表明的Turbo C差在优化代码,并把堆栈上的一切,而GCC是更积极,并保持它在寄存器或它扔了出去都在一起,因为这三个变量没有什么目的。

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

更新:

作为一个解释:我假设的printf()将始终以它的参数从栈中,因为它是一个变量参数列表的功能。或者是否有人知道任何其他调用约定功能如printf()?此外,我假设没有必要在堆栈上放置其他任何东西,因为没有其他变量。所以这个错误的电话printf将打印什么在main()的堆栈顶部。但是,在我的假设不成立的情况下,可能还有其他体系结构和调用约定。

+3

鉴于printf是一个库函数,我无法看到编译器如何能够选择将参数传递给它的方式。当编译库并且编译器必须符合时才选择调用约定。 – torak 2010-10-01 14:42:39

+0

优化不在_printf()_的调用中,而是存储_main()_中的局部变量。有问题的调用_printf()_只是揭示栈上的内容。 – Codo 2010-10-02 15:32:00

4

这是未定义的行为。

使用优化编译器时,这3个值可能会因未使用而优化。它会打印垃圾。

0

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

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

2

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

3

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

+3

而编写代码的程序员并不是“正在做”正确的“事情”! – 2010-10-01 15:08:27

1

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

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

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

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

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

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

当你得到一个局部变量的地址时,编译器会尝试将其锁定到一个特定的地址(可能通过将其存储在堆栈中)。

当大多数编译器查看您的代码时,他们将会看到这些局部变量的名称在声明后不再使用,并且可能决定不在任何位置存储它们的值。即使它将这些值存储在堆栈中,它也可能在设置调用printf之前将其他值推入堆栈。就像编译器不必保留你命名的变量一样,它也可以自由创建它自己的临时变量。