C编程printf("%d",50.2);

ale*_* jw -1 c floating-point int printf

#include <stdio.h>

int main(void) {
    printf("%d\n", 50.2);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

〜当我执行它时.

在此输入图像描述

50.2的二进制是(0100 0010 0100 1000 1100 1100 1100 1101).

所以,我预计1,112,067,277,但是,值不是,也不是固定的.

每次都会改变这些值,为什么?

Sou*_*osh 8

这是因为,对格式说明符使用错误的参数类型会调用未定义的行为.

引用C11,章节§7.21.6.1,fprintf()

d,i      该int参数被转换为符号十进制

这告诉我们%d期望一个类型int和的参数,

[....]如果任何参数不是相应转换规范的正确类型,则行为未定义.

所以,你传递一个 double(通常,甚至一个float参数也被提升为double.),其中a int是预期的.


Ctx*_*Ctx 7

看似随机值的原因是,在您的平台上printf()需要浮点/双参数的其他寄存器中的整数参数.在x86_64上,例如%esi(int)与%xmm0(float)

根据C标准,这是可以的,因为你因为错误的转换说明符而调用了未定义的行为.


Lun*_*din 6

问题是你在printf中使用了错误的格式说明符,%d而不是%f.这会调用未定义的行为.

每当您调用未定义的行为时,都不会有任何确定性或预期的输出.当你有未定义的行为时,编译器可以继续进行奇怪的假设,例如"从未使用过这个浮点字面值,所以不需要为它分配内存".这意味着您可能最终打印垃圾内存位置甚至导致程序崩溃.因此,分析未定义行为给出某种结果的原因并不是一项有意义的任务.

为了保证确定性行为,您必须执行以下操作:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>

int main(void) 
{
  const double number = 50.2;
  union
  {
    double  d;
    uint8_t u8 [sizeof(double)];
  } u = { number };

  printf("Binary representation of %f:\n", number);
  for(size_t i=0; i<sizeof(double); i++)
  {
    printf("%.2" PRIx8 " ", u.u8[i]);
  }
  printf("\n\n");
  printf("Integer (nonsense) representation of %f:\n", number);
  int i;
  memcpy(&i, u.u8, sizeof(int));
  printf("%d", i);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Binary representation of 50.200000:
9a 99 99 99 99 19 49 40

Integer (nonsense) representation of 50.200000:
-1717986918
Run Code Online (Sandbox Code Playgroud)

这是在一台机器上,其中double是8字节和整数4字节/小端,这意味着你将4个最低有效字节作为一些无意义输出(即数字9999999Ah).