c++ 为什么我可以将int和BOOL转换为void*,而不能转换为float?

cunj1qz1  于 2023-01-28  发布在  其他
关注(0)|答案(4)|浏览(203)

void*是C语言及其衍生语言的一个有用特性。例如,可以使用void*在C++类中存储目标C对象指针。
我最近在做一个类型转换框架,由于时间限制,我有点懒-所以我使用了void*......这就是这个问题出现的原因:
为什么我可以将int类型转换为void*,而不能将float类型转换为void*?

vlurs2pr

vlurs2pr1#

BOOL不是C++类型,它可能是typedef或在某个地方定义的,在这些情况下,它将与int相同。例如,Windows在Windef.h中有以下内容:

typedef int                 BOOL;

因此,您的问题简化为:为什么可以将int类型转换为void*,而不能将float类型转换为void*?
int到void* 是可以的,但通常不推荐(有些编译器会警告),因为它们在表示上本质上是相同的。指针基本上是一个整数,指向内存中的地址。
float到void* 是不正确的,因为对float值的解释与表示它的实际位不同。例如,如果执行以下操作:

float x = 1.0;

它的作用是将32位内存设置为00 00 80 3f(IEEE单精度浮点值1.0的实际表示)。2当你将一个浮点数强制转换为void* 时,解释是不明确的。3你指的是指向内存中位置1的指针吗?4还是指向内存中位置3f800000(假定为小字节序)的指针?
当然,如果你确定了你想要这两种情况中的哪一种,总有办法绕过这个问题。例如:

void* u = (void*)((int)x);        // first case
  void* u = (void*)(((unsigned short*)(&x))[0] | (((unsigned int)((unsigned short*)(&x))[1]) << 16)); // second case
ssm49v7z

ssm49v7z2#

指针通常由机器内部表示为整数。C允许你在指针类型和整数类型之间来回转换。(指针值可以转换为一个足够大的整数来容纳它,也可以转换回来。)
使用void*来保存非常规的整数值。语言不能保证它能工作,但是如果你想马虎一下,把自己限制在Intel和其他常见的平台上,它基本上可以勉强应付。
实际上,你所做的是使用void*作为一个通用容器,不管机器使用多少字节作为指针,这在32位和64位机器之间是不同的,所以在32位平台上将long long转换为void*会丢失一些位。
对于浮点数,(void*) 10.5f的意图是不明确的。您想将10.5舍入为整数,然后将其转换为无意义指针吗?不,您想将FPU使用的位模式放入无意义指针中。这可以通过赋值float f = 10.5f; void *vp = * (uint32_t*) &f;来实现,但要注意这只是无意义的:指针不是位的通用存储器。
顺便说一下,最好的通用位存储是char数组,语言标准保证内存可以通过char*操作,但是您必须注意数据对齐要求。

y1aodyip

y1aodyip3#

Standard表示 *752整数可以转换为任何指针类型 *。没有表示任何关于指针-浮点转换的内容。

nzk0hqpo

nzk0hqpo4#

考虑到您希望将float值转换为void *,有一个使用类型双关语的变通方案。
这里有一个例子。

struct mfloat {
        union {
            float fvalue;
            int ivalue;
        };
    };

    void print_float(void *data)
    {
        struct mfloat mf;

        mf.ivalue = (int)data;
        printf("%.2f\n", mf.fvalue);
    }

    struct mfloat mf;
    mf.fvalue = 1.99f;
    print_float((void *)(mf.ivalue));

我们使用union将浮点值(fvalue)转换为void* 的整数(ivalue),反之亦然

相关问题