7

在多项选择测试中提出了一个问题:以下程序的输出将是什么:

#include <stdio.h>

int main(void)
{
    int a = 10, b = 5, c = 2;

    printf("%d %d %d\n");

    return 0;
}

并且选择是 10、5 和 2 的各种排列。出于某种原因,它适用于我们在大学使用的 Turbo C++。但是,当使用 gcc(启用 -Wall 时会发出警告)或 clang(启用 -Wformat 并默认发出警告)或在 Visual C++ 中编译时,它不会。正如预期的那样,输出是垃圾值。我的猜测是,这与 Turbo C++ 是 16 位并在 32 位 Windows XP 上运行的事实有关,或者 TCC 在标准方面很糟糕。

4

5 回答 5

20

代码具有未定义的行为

在 Turbo C++ 中,这三个变量恰好位于堆栈上缺少printf()参数的确切位置。这会导致未定义的行为通过打印“正确”值来表现出来。

但是,您不能合理地依赖这种情况。即使是对构建环境的最轻微更改(例如不同的编译器选项)也可能以任意令人讨厌的方式破坏事物。

于 2013-08-22T19:30:47.353 回答
4

它是一个undefined behaviour. 所以它可以是任何东西。

尝试使用

printf("%d %d%d", a,b,c)

原因:-局部变量在堆栈上被调用,并且 Turbo C++ 中的 printf 以它们在堆栈中分配的相同顺序查看它们。

建议(来自评论):-

了解为什么它在特定编译器中以特定方式运行可能有助于诊断问题,但不要对这些信息进行任何其他使用。

于 2013-08-22T19:29:39.340 回答
4

这里的答案是程序可以做任何事情——这是未定义的行为。根据printf()s 文档(强调我的):

默认情况下,参数按给定顺序使用,其中每个 '*' 和每个转换说明符都要求下一个参数(如果给定的参数数量不足,则会出错)

如果您的多项选择测试没有选择“未定义行为”,那么它就是一个有缺陷的测试。在未定义行为的影响下,对这样的多项选择题的任何答案在技术上都是正确的。

于 2013-08-22T19:30:01.970 回答
3

实际发生的是参数通常在调用堆栈上传递。局部变量也在调用堆栈上传递,因此printf()可以看到这些值,无论编译器决定将它们存储在那里的顺序如何。

这种行为以及许多其他行为在未定义行为的保护下是允许的

于 2013-08-22T19:31:17.517 回答
2

不,它与建筑无关。它与 TurboC++ 如何处理堆栈有关。变量abc是局部变量,因此分配在堆栈中。 printf还期望堆栈中的值。显然,TurboC++ 不会在局部变量之后向堆栈添加任何其他内容,并且printf能够将它们作为参数。只是巧合。

于 2013-08-22T19:34:24.460 回答