为什么这个节目是给意外的数字(例如:2040866504,-786655336)?
#include <stdio.h>
int main()
{
int test = 0;
float fvalue = 3.111f;
printf("%d", test? fvalue : 0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么要打印意外的数字而不是0?它应该做隐式的类型转换吗?这个程序用于学习目的并不严重.
Dav*_*rtz 18
最有可能的是,您的平台在浮点寄存器中传递浮点值,在不同寄存器(或堆栈)中传递整数值.你告诉你printf寻找一个整数,所以它在寄存器中查找整数(或在堆栈中).但是你传递了它float,所以零被放置在printf从未看过的浮点寄存器中.
三元运算符遵循语言规则来决定其结果的类型.它有时不能是整数,有时候是浮点数.这些可能是不同的大小,存储在不同的地方,等等,这将导致无法生成合理的代码来处理两种可能的结果类型.
这是猜测.也许正在发生一些完全不同的事情.由于某种原因未定义未定义的行为.如果没有丰富的平台和编译器细节经验和知识,这些事情是无法预测的,也很难理解.永远不要让别人说服UB是好的或安全的,因为它似乎适用于他们的系统.
hac*_*cks 11
因为您%d用于打印float值.使用%f.使用%d打印float值调用未定义的行为.
编辑:关于OP的评论;
为什么打印随机数而不是0?
编译此代码时,编译器应该给出警告:
[Warning] format '%d' expects argument of type 'int', but argument 2 has type 'double' [-Wformat]
Run Code Online (Sandbox Code Playgroud)
此警告是自解释的,这行代码正在调用未定义的行为.这是因为,转换规范%d指定printf将int值从二进制转换为十进制数字字符串,而%f对float值进行相同操作.在传递fvalue编译器时,知道它是float类型的,但另一方面,它看到printf期望一个类型的参数int.在这种情况下,有时它会按照您的预期进行,有时它会达到我的预期.有时它会做到没人想到的(David Schwartz的评论).
参见测试用例1和2.它工作正常%f.
它应该做隐式的类型转换吗?
没有.
虽然现有的upvoted答案是正确的,但我认为它们太过技术性而忽略了初学程序员可能具有的逻辑:
让我们看一下在某些主题中引起混淆的陈述:
printf("%d", test? fvalue : 0);
^ ^ ^ ^
| | | |
| | | - the value we expect, an integral constant, hooray!
| | - a float value, this won't be printed as the test doesn't evaluate to true
| - an integral value of 0, will evaluate to false
- We will print an integer!
Run Code Online (Sandbox Code Playgroud)
编译器看到的有点不同.他同意test意义的价值false.他同意使用fvaluea float和0整数.但是,他了解到三元运算符的不同可能结果必须是同一类型!int而float不是.在这种情况下," float胜利" 0变成0.0f!
现在printf不是类型安全的.这意味着您可以错误地说"打印一个整数"并传递一个浮点数,而无需编译器注意.恰好发生了这种情况.无论价值test是多少,编译器推断出结果都是类型的float.因此,您的代码相当于:
float x = 0.0f;
printf("%d", x);
Run Code Online (Sandbox Code Playgroud)
此时,您会遇到未定义的行为.float根本不是integral预期的东西%d.
观察到的行为取决于您正在使用的编译器和机器.你可能会看到跳舞的大象,虽然大多数终端都不支持这种大象.
| 归档时间: |
|
| 查看次数: |
957 次 |
| 最近记录: |