因为printf()是一个函数,如果发生错误,它返回成功或负值写入的字符数,看这个例子,预期的输出是零。
#include <stdio.h>
int main(void)
{
printf("%d");
return 0;
}
现在当我添加更多%d 时:http://ideone.com/brw5vG 输出更改为: 0 134513819 -1216430092 134513808
我无法弄清楚随机垃圾值是什么?输出中也有负值,负值可以证明错误是正确的,所以任何人都可以确切地指出这里的错误是什么吗? 请简明扼要,具体。感谢。
答案 0 :(得分:5)
因为"%d"
表示期望整数。你没有传递任何东西,所以你得到了未定义的行为。
请注意,g ++ 4.8.2提供了一个有用的警告:
警告:格式'%d'需要匹配的'int'参数[-Wformat =]
类似于clang ++ 3.4:
警告:比数据参数[-Wformat]
更多'%'次转化
答案 1 :(得分:3)
预期的输出为零
printf("%d");
您的程序调用未定义的行为时,您不应该期待任何事情。
(C99,7.19.6.1p2)“[...]如果格式的参数不足,则行为是 未定义。[...]“
答案 2 :(得分:2)
您错误地将格式字符串指定为printf
这是undefined behavior,您应该对结果没有任何期望。通过指定%d
,您告诉printf
期望您未提供的int
参数。
如果我们查看C99草案标准部分7.19.6.1
fprintf函数,其中还包含pritnf
格式说明符:
[...]如果格式的参数不足,则行为未定义。[...]
答案 3 :(得分:1)
问题在于你如何提出问题;你认为它“应该是0”事实是,这是未定义的行为,并且printf
将替换堆栈中发生的任何%d
。
答案 4 :(得分:1)
您的代码调用未定义的行为。任何事情都可能发生。
C11 标准部分7.21.6
格式化输入/输出功能:
如果任何参数不是相应转换规范的正确类型,则行为未定义。
您没有为相应的%d
说明符传递任何参数。
答案 5 :(得分:0)
手头有两个问题:第一个是为什么编译器没有发出关于这个对printf()
的错误调用的错误,第二个是为什么你得到垃圾输出。我会一次一个回答。
printf()
是一个棘手的功能。虽然大多数函数都传递了一定数量的参数,但printf()
却不同。
例如,如果我们采用这个简单的函数:
int max(int a, int b) {
if (a > b) return a;
else return b;
}
您可以看到此函数始终接收2个参数。这也是编译器知道的东西,并在编译代码时强制执行。这就是max(4)
之类的通话不起作用的原因。编译器将看到我们传递max()
1个参数而不是2,它将发出错误。
printf()
是一个接受可变数量参数的函数,这个数量由格式字符串中格式说明符(以%开头的东西)的数量决定。这意味着编译器在编译时无法知道传递给printf的参数量是否足够(或者可能太多)。
您打印垃圾的原因是函数如何读取其输入参数。函数的所有输入参数都驻留在堆栈上。在调用函数之前将它们推入堆栈,然后由函数解决。在这种情况下,printf()
期望除了格式字符串之外还有一个额外的参数(因为%d
),因此它会查找其第二个参数可能已经存在的地址。唉,该参数未被传递,因此它实际上会查看堆栈中可能包含其他任何内容的位置(返回地址,帧指针,封闭范围的局部变量或其他)。
您可以详细了解函数调用的工作原理here。