C 意外输出将浮点强制转换打印为int #包括 int main() { 浮点数a=12.5; printf(“%d\n”,a); printf(“%d\n”、*(int*)&a); 返回0; }

C 意外输出将浮点强制转换打印为int #包括 int main() { 浮点数a=12.5; printf(“%d\n”,a); printf(“%d\n”、*(int*)&a); 返回0; },c,pointers,C,Pointers,此外,如何解释表达式*(int*)&a?它获取浮点的地址,将其强制转换为整数指针,然后将其作为整数取消引用。完全错了 这里至少有两件事不对: 没有人说int和float的指针需要大小相同 浮点数的表示形式与有符号整数的表示形式完全不同 因此,第二个printf的输出(如果它没有发生崩溃,因为根据第一点,它是未定义的行为)可能是一个奇怪的、巨大的数字。如果您使用该行printf(“%08X\n”,*(unsigned int*)&a)然后打印浮点数的二进制表示形式。详细信息。此代码的作者试图将

此外,如何解释表达式
*(int*)&a

它获取浮点的地址,将其强制转换为整数指针,然后将其作为整数取消引用。完全错了

这里至少有两件事不对:

  • 没有人说int和float的指针需要大小相同
  • 浮点数的表示形式与有符号整数的表示形式完全不同

因此,第二个printf的输出(如果它没有发生崩溃,因为根据第一点,它是未定义的行为)可能是一个奇怪的、巨大的数字。

如果您使用该行
printf(“%08X\n”,*(unsigned int*)&a)
然后打印浮点数的二进制表示形式。详细信息。

此代码的作者试图将浮点的位重新解释为int,但
*(int*)&a
调用未定义的行为,现代编译器可能不会执行代码作者的意图。将错误类型的参数传递给
printf
是更糟糕的未定义行为;它肯定不会在x86_64这样的现代拱门上工作。相反,您可以使用:

#include <stdio.h>
int main()
{
    float a = 12.5;

    printf("%d\n", a);
    printf("%d\n", *(int *)&a);

    return 0;
}
#包括
int main()
{
浮点数a=12.5;
int b;
成员(b&a、b&a、b的大小);
printf(“%d\n”,b);
返回0;
}
以获得所需的效果。

大小(float)和大小(double)往往是至少sizeof(short)和sizeof(int)的倍数(为了满足不同的需要,甚至IEEE浮点标准也允许多种浮点格式)

假设前面提到的未定义指针行为不会杀死程序,在大多数环境中,这只会获取其中一个int的位,并单独打印出来。浮点数的内部结构确保这与原始浮点数有很大的不同

#include <stdio.h>
int main()
{
  float a = 12.5;
  int b;
  memcpy(&b, &a, sizeof b);
  printf("%d\n", b);
  return 0;
}
printf(“%d sizeof(short)\n”,int(sizeof(short)); printf(“%d sizeof(int)\n”,int(sizeof(int)); printf(“%d sizeof(float)\n”,int(sizeof(float)); printf(“%d sizeof(double)”,int(sizeof(double)); printf(“%d个sizeof(长双精度)”,int(sizeof(长双精度));
我的编译器对此进行标记并发出严厉警告

printf( "%d sizeof(short)\n", int(sizeof(short)) ); printf( "%d sizeof(int)\n", int(sizeof(int)) ); printf( "%d sizeof(float)\n", int(sizeof(float)) ); printf( "%d sizeof(double)\n", int(sizeof(double)) ); printf( "%d sizeof(long double)\n", int(sizeof(long double)) );
想这样做的原因是什么?

不,它调用未定义的行为。@R:Hm,我想转换到
无符号字符*
(您可以这样做)然后打印
sizeof(float)
单位会更安全。是的,或者像我那样使用
memcpy
,让它更简单。顺便说一下,这里有一件有趣的事:;你知道为什么printf(“%d”,a)总是打印0,而不是像int那样解释浮点值吗?试图在printf-man中找到答案,但还不知道。@Маааа:您在x86_64上吗?如果是这样的话,这就可以解释它。@Маimk_ааСааааааааа。它不会将
a
转换为整数,它只是将这些位解释为“这些无意义的位是一个有符号整数”。如果你假设(基本上所有现实世界的系统都是)32位的二补
int
和IEEE单精度
float
。@R:你能详细说明为什么printf(“%d”,a)是没有意义的吗打印0。我在gcc上获得了此输出。要犯错误并学习…)
$ make foolish
cc     foolish.c   -o foolish
foolish.c: In function ‘main’:
foolish.c:5: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘double’
$ ./foolish
1606416928
1095237632
$