为什么printf()在应该为0时给出随机输出?

时间:2014-01-14 19:28:37

标签: c gcc printf c99

因为printf()是一个函数,如果发生错误,它返回成功或负值写入的字符数,看这个例子,预期的输出是

#include <stdio.h>    
int main(void) 
{     
printf("%d");    
return 0;
}

现在当我添加更多%d 时:http://ideone.com/brw5vG 输出更改为:   0 134513819 -1216430092 134513808

我无法弄清楚随机垃圾值是什么?输出中也有负值,负值可以证明错误是正确的,所以任何人都可以确切地指出这里的错误是什么吗? 请简明扼要,具体。感谢。

6 个答案:

答案 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

相关问题