将数据从float复制到int,而不强制转换数据

  • 本文关键字:数据 转换 int float 复制 c
  • 更新时间 :
  • 英文 :


在下面的代码中,我尝试将数据从float f逐位复制到int I,而不进行任何数据转换。我将f的地址强制转换为(int*),并在将其分配给I时取消引用该地址;f作为一个int指针,当(int*)f被取消引用并分配给i时,它不会进行类型转换。但这不起作用,我不明白为什么。

void main(){
  float f=3.0;
  int i;
  /* Check to make sure int and float have the same size on my machine */
  printf("sizeof(float)=%dn",sizeof(float)); /* prints "sizeof(float)=4" */
  printf("sizeof(int)=%dn",sizeof(int)); /* prints "sizeof(int)=4" */
  /* Verify that &f and (int*) &f have the same value */
  printf("&f = %pn",&f); /* prints &f = 0x7ffc0670dff8 */
  printf("(int*) &f = %pn",(int*) &f); /* prints (int*) &f = 0x7ffc0670dff8 */
  i=*((int*) &f);
  printf("%fn", i); /* prints 0.000000 (I would have expected 3.000000) */
  return;
}

通过类型转换进行赋值,将原始的4字节数据从一个变量复制到另一个变量。问题是32位浮点变量中的3不像整数变量中的三那样存储。

例如,Mac上的3位64位浮点格式存储为0x4e808000。将其赋值为整数将产生1077936128。

请参阅https://en.wikipedia.org/wiki/IEEE_floating_point或http://www.madirish.net/240或https://users.cs.duke.edu/~raw/cps104/TWFNotes/foating.html

为同一对象创建两个不相关类型的指针违反了严格的别名规则。您需要避免这种情况,因为在复杂的代码中,它可能会导致编译器生成不符合您要求的二进制文件。这也是未定义的行为。

intfloat之间更改C中位模式类型的正确方法是完全避免指针,并使用并集:

union int_float { int i; float f; };
int ival = (union int_float){ .f = 4.5 }.i;
float fval = (union int_float){ .i = 45 }.f;

结果可能略有不同。请确保检查浮动类型和整数类型的大小是否相同,否则数据将丢失/生成垃圾数据。

请注意,以这种方式生成的值可能不是目标类型的有效元素(当非零整数值被解释为浮点零时,尽管没有所有的零位模式,但这或多或少就是您在上面看到的情况),这可能会导致后续的未定义或意外行为。确保验证输出。

转换后,您将获得存储在变量i中的整数。因此,如果你想打印这样一个值,你必须使用:

printf("%dn", i); /* prints 1077936128 */

现在printf将正确解释内存位并打印正确的值。这不是一个演员阵容,而是一个有点像你说的复制品。请记住((int)&f) 将该指针取消引用为int值。在int和float大小不同的机器上,它不会做你认为的事情。

如果int和float的大小相同,则复制的另一种方法是:

memcpy(&i, &f, sizeof f);

在复制了内存区域中包含的四个字节之后,如果我们试图将内容打印为四个十进制值的序列,我们可以理解刚刚发生的重新分发:

用于浮动:

3 160 0 3

对于整数

0 204 204 0

这意味着这四个字节的管理方式与计算机不同,具体取决于representation的类型:int或float。

最新更新