即使我们将正分数放入双重类型[重复],符号位为1的原因
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了即使我们将正分数放入双重类型[重复],符号位为1的原因相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
我把正值放入变量中,哪个类型是double。当我看到内存的内容时,符号位为1.我认为它应该是0,但它可能是错误的。为什么符号位是1?
#include<stdio.h>
int main(){
int num=116;
union {float x; int i;} u4;
union {double x; long long int i;} u8;
u4.x = (float) num/10000.0;
u8.x = (double) num/10000.0;
printf("%lx
",u4.i);
printf("%lx
",u8.i);
printf("%.30f
",u4.x);
printf("%.30f
",u8.x);
return 0;
}
输出:
3c3e0ded
a5119ce0
0.011599999852478504000000000000
0.011599999999999999000000000000
a5119ce0是double类型的输出。 a5119ce0的意思是
1010 0101 0001 0001 1001 1100 1110 0000
并且它的符号位为1表示这是负数。
3c3e0ded是float类型的输出。 3c3e0ded意味着
0011 1100 0011 1110 0000 1101 1110 1101
我也很困惑,使用float和double获得了相同的长度结果。
你打错了。请记住,C对printf的输入一无所知。你指定%lx来打印double,有效地只打印前32个字节。您应该使用%ll打印64位整数(在C中称为long long
)。
要了解打印双精度的32位,您还必须了解big-endian和little-endian。基本上,不同的CPU将最低有效位置于第一个或最后一个,这意味着根据目标CPU,您将获得最低有效32位或最高有效位。 x86和x64(您可能正在运行代码)是小端BTW。
如果编译时出现警告,编译器可能会指出你的错误。例如,与gcc
:
$ gcc -Wall main.c
main.c: In function ‘main’:
main.c:12:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
printf("%lx
",u4.i);
^
main.c:12:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
main.c:13:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long long int’ [-Wformat=]
printf("%lx
",u8.i);
^
main.c:13:12: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long long int’ [-Wformat=]
进行更正表明:
printf("%x
",u4.i);
printf("%llx
",u8.i);
编译时没有警告并产生预期的输出:
3c3e0ded
3f87c1bda5119ce0
0.011599999852478504180908203125
0.011599999999999999200639422270
这是您的代码的修改版本,用于打印出IEEE-754格式的浮点值,因为它存储在内存中。注意big-endian和little-endian的快速和脏测试,这会影响我们的打印方式:
int main()
{
unsigned int test = 0x01020304;
int isBigEndian = (1 == *(char*)&test);
float num = 3.14;
// breaking the rules here, but this will work for demonstration purposes
unsigned char* ptr = (unsigned char*)&num
// we're assuming sizeof(float) == 4
if (isBigEndian)
printf("0x%02x%02x%02x%02x
", ptr[0], ptr[1], ptr[2], ptr[3]);
else
printf("0x%02x%02x%02x%02x
", ptr[3], ptr[2], ptr[1], ptr[0]);
return 0;
}
以上是关于即使我们将正分数放入双重类型[重复],符号位为1的原因的主要内容,如果未能解决你的问题,请参考以下文章