pie*_*okr 10 c floating-point integer
#include<stdio.h>
int main()
{
float a;
printf("Enter a number:");
scanf("%f",&a);
printf("%d",a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我gcc
在Ubuntu中运行该程序.对于价值观 -
3.3 it gives value 1610612736
3.4 it gives value 1073741824
3.5 it gives value 0
3.6 it gives value -1073741824
4 it gives value 0
5 it gives value 0
Run Code Online (Sandbox Code Playgroud)
怎么了?为什么打印这些值?我故意这样做,但想了解为什么会这样.详情谢谢!
ken*_*ytm 23
该printf
函数不知道您传入的格式类型,因为该部分是可变参数.
int printf(const char* format, ...);
// ^^^
Run Code Online (Sandbox Code Playgroud)
在C标准中,传递a float
将自动提升为double
(C11§6.5.2.2/ 6),并且在调用者方面不会做任何其他事情.
在里面printf
,因为它不知道那个...
东西的类型(§6.7.6.3/ 9),它必须使用来自其他地方的提示 - 格式字符串.既然你已经过去了"%d"
,它就告诉了函数,这int
是预期的.
根据C标准,这会导致不确定的行为(§7.21.6.1/ 8-9),其中包括打印一些奇怪数字的可能性,即故事结束.
但究竟发生了什么?在大多数平台中,a double
表示为" IEEE 754 binary64 "格式,而表示float
为binary32格式.您输入的数字将转换为浮点数,只有23位有效值,这意味着数字将近似如下:
3.3 ~ (0b1.10100110011001100110011) × 2¹ (actually: 3.2999999523162842...)
3.4 ~ (0b1.10110011001100110011010) × 2¹ (actually: 3.4000000953674316...)
3.5 = (0b1.11 ) × 2¹ (actually: 3.5)
3.6 ~ (0b1.11001100110011001100110) × 2¹ (actually: 3.5999999046325684...)
4 = (0b1 ) × 2² (actually: 4)
5 = (0b1.01 ) × 2² (actually: 5)
Run Code Online (Sandbox Code Playgroud)
现在我们将它转换为double,它有53位的重要性,我们必须在这些数字的末尾插入30个二进制"0",以产生例如
3.299999952316284 = 0b1.10100110011001100110011000000000000000000000000000000 ×2¹
Run Code Online (Sandbox Code Playgroud)
这些主要是为了得出这些数字的实际表示,它们是:
3.3 ? 400A6666 60000000
3.4 ? 400B3333 40000000
3.5 ? 400C0000 00000000
3.6 ? 400CCCCC C0000000
4 ? 40100000 00000000
5 ? 40140000 00000000
Run Code Online (Sandbox Code Playgroud)
我建议使用http://www.binaryconvert.com/convert_double.html来查看它如何分解为± m ×2 e格式.
无论如何,我认为你的系统在正常设置下是x86/x86_64/ARM,这意味着数字是使用little-endian格式在内存中布局的,所以传递的参数就像
byte
#0 #1 ... #4 ... #8 ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 08 | 10 | 02 | 00 | | 00 | 00 | 00 | 60 | 66 | 66 | 0A | 40 | ....
+----+----+----+----+ +----+----+----+----+----+----+----+----+
address of "%d" content of 3.299999952316284
(just an example)
Run Code Online (Sandbox Code Playgroud)
在里面printf
,它使用格式字符串"%d"
,解析它,然后发现int
因为%d需要a,所以从可变参数输入中获取4个字节,即:
byte
#0 #1 ... #4 ... #8 ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
: 08 : 10 : 02 : 00 : | 00 | 00 | 00 | 60 | 66 : 66 : 0A : 40 : ....
+ - -+ - -+ - -+ - -+ +====+====+====+====+ - -+ - -+ - -+ - -+
address of "%d" ~~~~~~~~~~~~~~~~~~~
this, as an 'int'
Run Code Online (Sandbox Code Playgroud)
因此,printf将接收0x60000000,并将其显示为十进制整数,即1610612736,这就是您看到该结果的原因.其他数字可以类似地解释.
3.3 ? ... 60000000 = 1610612736
3.4 ? ... 40000000 = 1073741824
3.5 ? ... 00000000 = 0
3.6 ? ... C0000000 = -1073741824 (note 2's complement)
4 ? ... 00000000 = 0
5 ? ... 00000000 = 0
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
416 次 |
最近记录: |