printf ("%d", <double> 的 c 行为

标签 c gcc compilation

为什么这段代码会打印无意义的值?如果有道理的话是什么?

printf("%d\n", 5.0 / 4);

顺便说一句,我知道我应该使用 %f 的格式说明符而不是%d 。但我想知道 c 到底做了什么。

奇怪的是,每次我运行编译的程序时,它都会打印不同的内容。它不是必须是确定性的吗?

据我观察,这段代码打印了类似的内容:

float c;
printf("%d\n", &c);

它们有什么关系吗?

当我尝试时:

float c;
printf("%d\n%d\n", c, &c);

这两个值之间有一个常数 252。 256 - sizeof(float) 也许? 将 c 声明为 double 会使差异为 0。

提前致谢!

更新:在不同的机器上编写相同的代码会产生不同的结果。(252 是 56。前者是 64 位 ubuntu 机器,后者是 64 位 OS X)

最佳答案

printf 的不同寻常之处在于它没有单一的函数签名。换句话说,没有机制可以自动获取您传递的实际参数并将它们转换为预期的类型。无论你试图通过什么,都会通过。如果您传递的类型与相应格式说明符期望的类型不匹配,您就会得到无意义的结果。

此外,如果您传递的不匹配类型与格式说明符期望的类型具有不同的大小,printf 最终可能会从堆栈中弹出随机垃圾,这与您的内容无关以为你通过了。

您问:“它不是必须是确定性的吗?”,答案是非常强调的“NO”!通过将错误类型的值传递给 printf,您调用了未定义的行为,这意味着任何事情都可能发生,而且绝对不必是同一件事两次.

(尽管不要求这样做,但某些编译器会查看格式字符串并尝试根据预期值检查您传递的值。例如,在 gcc 下,您的第一个代码片段会收到警告“format “%d”需要类型“int”,但参数 2 的类型为“double””。但我不知道有哪个编译器会尝试进行转换来“修复”参数。)

关于printf ("%d", <double> 的 c 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35900011/

相关文章:

c++ - 海湾合作委员会的错误?关于模板类中友元函数的访问控制问题

c - 拆分一个字符串并组合 2 个字符串 - C

Kotlin 通用接口(interface)解析器

java - Intellij - 将默认输出路径设置为 gradle 输出

你能帮我一个符号状态表和嵌套开关吗?来自 Illustrationing C- Donald Alcock 的练习

c - 我尝试理解 [c 代码 -> 汇编] 代码

c - 在循环之间移动数组

c - gcc 实际上是否将原型(prototype)视为函数并且它们的参数是否分配了内存?

windows - 在 Windows 上从 Matlab 编译 .sh 文件

c - 输出有时会失败