printf()'神秘地'知道我打算打印什么?

时间:2013-09-17 04:25:34

标签: c printf

我忘了将附带的变量添加到printf()调用中。 printf()如何知道我想要打印的内容?

int successful = 0;//Flag
printf("\nEnter a number to search for: ");
scanf("%d", &data);
successful = search(list, data);
successful? printf("\n'%d' was found\n\n", data) : printf("\n'%d' was NOT found\n\n");

违规代码是最后一行三元表达式的最终“else”。我已经运行了几十次,似乎总是在输出中打印正确的参数。

: printf("\n'%d' was NOT found\n\n");

这每次仍然有效吗?

2 个答案:

答案 0 :(得分:19)

它似乎可行,但不要依赖于此。

它可能有效,因为你最近的函数调用,

successful = search(list, data);

data值留在堆栈上的适当位置。


在这里提一下,如果你忽略在声明单个局部变量的函数中包含一个return语句,有时可能会出现类似的 serendipity

int wowee () {
    int val;
    val = 12;

    // <-- no return statement!
}

有时,将返回局部变量val,这可能是由于相同类型的堆栈重用。但这也是未定义的行为,即使它恰好起作用。


这两种情况的道德标准是启用更多编译器警告。编译器可以诊断这些问题,甚至检查格式字符串是否与传递给 prinf -family函数的变量类型相匹配。

答案 1 :(得分:12)

糟糕!这是“未定义的行为”。

printf("\n'%d' was NOT found\n\n"); // undefined behavior

“未定义的行为”是一个技术术语,基本上意味着... 任何都可能发生。也许正确的事情可能发生,也许程序会崩溃,或者它可能会完全做其他事情。

在这种情况下,您想要的值可能已经在正确的位置堆栈中,因此当printf()何时获取其参数时,它获得了正确的值。这在很大程度上取决于优化的使用和您正在使用的特定ABI,特别是,并非所有ABI都将值放在堆栈上以进行非可变函数调用。

successful = search(list, data);
//                        ^^^^ places "data" on stack as second argument

如果将程序编译为64位,它可能不再起作用,因为最常见的x64 ABI使用寄存器作为前四个非可变参数。

它不会改变您的代码错误的事实,如果您想要始终如一地获得正确答案,则需要修复它。