简体   繁体   English

将 void* 转换为 int*

[英]Converting void* to int*

We have two variables fa and fb of float type.我们有两个浮点类型的变量 fa 和 fb。 We copy blocks of memory into variables of type void*.我们将内存块复制到 void* 类型的变量中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    float fa = 2.11, fb = 2.2;
    void *a, *b;
    int *ffa, *ffb;

    a = malloc(sizeof(float));
    b = malloc(sizeof(float));
    memcpy(a, &fa, sizeof(float));
    memcpy(b, &fb, sizeof(float));

    ffa = (int*)a;
    ffb = (int*)b;

    printf("ffa = %d\n", *ffa);
    printf("ffb = %d\n", *ffb);

    return 0;
}

After converting them to int type, we get huge numbers.将它们转换为 int 类型后,我们得到了巨大的数字。 Why is this happening?为什么会这样?

ffa = 1074203197
ffb = 1074580685

We copy blocks of memory into variables of type void*.我们将内存块复制到 void* 类型的变量中。

Careful.小心。 You are copying into memory pointed to by variables of type void * .您正在复制到类型为void *的变量指向的内存中。 But, yes, you are copying blocks of memory .但是,是的,您正在复制内存块 In particular, you are not assigning values , and therefore you have no possibility of converting values .特别是,您没有分配 values ,因此您不可能转换 values

After converting them to int type, we get huge numbers.将它们转换为 int 类型后,我们得到了巨大的数字。

Again, you have to be careful with your language.同样,你必须小心你的语言。 You did not convert anything to int type.您没有将任何内容转换为int类型。 You converted two pointers from void * type to int * type.您将两个指针从void *类型转换为int *类型。 You converted the pointers.您转换了指针。 You did not convert the pointed-to values!没有转换指向的值!

If you had said如果你说过

float fa = 2.11;
int ia = (int)fa;

you would have converted the floating-point number 2.11 to the integer 2. But that's not what you did.您应该将浮点数 2.11 转换为整数 2。但这不是您所做的。

In IEEE-754 floating point , the number 2.11 is represented by the bit pattern 0x40070a3d .IEEE-754 浮点中,数字 2.11 由位模式0x40070a3d表示。 (How it is that those crazy-looking bits actually represent the number 2.11 is a fascinating story, but beyond the scope of this answer.) And the hexadecimal number 0x40070a3d in decimal is 1074203197, which is precisely the number you saw. (这些看起来很疯狂的位实际上如何表示数字 2.11 是一个引人入胜的故事,但超出了这个答案的范围。)十进制的十六进制数字0x40070a3d是 1074203197,这正是您看到的数字。

When you say当你说

ffa = (int*)a;

you are not saying, "Hey compiler, those bits representing the floating-point number 2.11, I want you to convert them to an integer for me."不是说,“嘿,编译器,那些代表浮点数 2.11 的位,我希望你帮我把它们转换成整数。” (Again, to do that, you'd want int ia = (int)fa; .) No, what this line says is "Hey, compiler, that pointer a pointing to some bits representing a floating-point number, I want to pretend they're a pointer pointing to an integer." (同样,要做到这一点,你需要int ia = (int)fa; 。)不,这行说的是“嘿,编译器,那个指针a指向一些代表浮点数的位,我想假装它们是一个指向整数的指针。”

In other words, you did not change the pointed-to bits.换句话说,您没有更改指向的位。 And, in a way, you didn't change the pointer, either: ffa points to the exact same spot in memory that a does.而且,在某种程度上,您也没有更改指针: ffa指向与a完全相同的内存位置。 But what you very importantly changed was the interpretation of the pointed-to bits.但是您非常重要的改变是对指向位的解释 a is a pointer to a spot in memory where we expect there to be a value of type float , while ffa is a pointer to a spot in memory where we expect there to be a value of type int . a是指向内存中某个点的指针,我们希望在该点有一个float类型的值,而ffa是一个指向内存中某个点的指针,我们希望在该点有一个int类型的值。

So if you say所以如果你说

printf("%f\n", *a);

you have a pointer, a , which is assumed to point to a float , and you use * to "take the contents of" the pointer, so you fetch the pointed-to value, and print it using %f , and you see 2.11 .你有一个指针a ,它被假定指向一个float ,你使用*来“获取”指针的内容,所以你获取指向的值,并使用%f打印它,你会看到2.11 .

But when you say但是当你说

printf("ffa = %d\n", *ffa);

you have a pointer, ffa , which is assumed to point to an int , and you use * to "take the contents of" the pointer, so you fetch the pointed-to value, and print it using %d , and you see 1074203197 .你有一个指针ffa ,它被假定指向一个int ,你使用*来“获取”指针的内容,所以你获取指向的值,并使用%d打印它,你会看到1074203197 .

You have used pointers to take the same bit pattern, sitting in the same spot in memory, and interpret it in two different ways.您已经使用指针来获取相同的位模式,位于内存中的相同位置,并以两种不同的方式对其进行解释。 Interpreted as type float , the bit pattern 0x40070a3d is 2.11.解释为float类型,位模式0x40070a3d为 2.11。 Interpreted as type int , the bit pattern 0x40070a3d is 1074203197.解释为int类型,位模式0x40070a3d为 1074203197。

This is a common (and powerful) use of pointers, although now that you're starting to understand it, I have to leave you with some cautions.这是指针的常见(和强大)用法,尽管现在您已经开始理解它,但我必须给您一些警告。 Taking bit patterns in memory and reinterpreting them as different types, as we've been doing here, is actually a little more complicated than this question has made it look.正如我们在这里所做的那样,在内存中获取位模式并将它们重新解释为不同的类型,实际上比这个问题看起来要复杂一些。 In practice, there are two real-world complications that come into play, alignment and strict aliasing .在实践中,有两种现实世界的复杂情况会发挥作用, 对齐严格混叠 At some point you may want to learn more about those.在某些时候,您可能想了解更多关于这些的信息。

This is happening because floats are not integers and are saved differently in memory.发生这种情况是因为浮点数不是整数,并且在内存中的保存方式不同。 Ints use methods like 2's or 1's complement while floats use methods like IEE.整数使用 2 或 1 补码等方法,而浮点数使用 IEE 等方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM