C 将32位浮点数转换为64位uint64\t

C 将32位浮点数转换为64位uint64\t,c,casting,floating-point,bit-manipulation,uint64,C,Casting,Floating Point,Bit Manipulation,Uint64,我有一个uint64\u t,我想在其中存储一个float,作为最右边的32位 基本上,我想要的是,给定一个floatf: |--------------------------------|--------------------------------| | 32 bits set to 0 | the 32 bits of our float | |================================|=========

我有一个
uint64\u t
,我想在其中存储一个
float
,作为最右边的32位

基本上,我想要的是,给定一个float
f

   |--------------------------------|--------------------------------|
   |         32 bits set to 0       |    the 32 bits of our float    |
   |================================|================================|
   ^                                                                 ^
   ^                      64-bit unsigned integer                    ^
   |-----------------------------------------------------------------|
我试过将其转换为
(uint_64t)f
,但结果有点奇怪


有什么想法吗?

假设您希望
uint64\t
包含浮点的表示,您可以执行以下操作:

uint32_t t;
memcpy(&t, &f, sizeof(t));
uint64_t val = t;

调用
memcpy
会将浮点的表示复制到大小相同的
uint32\u t
。随后的赋值有效地将
val
的高阶字设置为0,低阶字设置为32位值。通过这种方式执行,它不依赖于endianness。

编辑:虽然我确实证明了下面的评论是正确的,但添加了此编辑是为了防止有人需要调整/洗牌C中的字节

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

int main()
{
    // test vars
    unsigned int testInt = 1;
    char *testChar = (char *)&testInt;

    // allocate an 64 bit unsigned integer set all bits to zero
    uint64_t i = 0;

    // define the float here
    float f = 3.14;

    printf("64 bits integer val before copy = %"PRId64"\n", i);
    printf("32 bits float val before copy   = %f\n", f);

    if (*testChar == 1) {
        // little endian
        printf("little endian system\n");
        *((float *)&i) = f; // copy float bit pattern to lower bytes
    }
    else {
        // big endian
        printf("big endian system\n");
        *((float *)&i + 1) = f; // copy float bit pattern to lower bytes
    }

    printf("64 bits integer val after copy  = %"PRId64"\n", i);

    return 0;
}
#包括
#包括
#包括
int main()
{
//测试变量
无符号整数测试=1;
char*testChar=(char*)&testInt;
//分配一个64位无符号整数,将所有位设置为零
uint64_t i=0;
//在这里定义浮动
浮点数f=3.14;
printf(“复制前64位整数val=%”PRId64“\n”,i);
printf(“复制前32位浮点值=%f\n”,f);
如果(*testChar==1){
//小恩迪亚
printf(“小端系统”);
*((float*)&i)=f;//将浮点位模式复制到较低的字节
}
否则{
//大端
printf(“big-endian系统”);
*((float*)&i+1)=f;//将浮点位模式复制到较低的字节
}
printf(“复制后的64位整数val=%”PRId64“\n”,i);
返回0;
}

,仅供参考,这不是转换。转换在保留值的同时改变了某物的表示形式。(理想情况下,该值会准确保留,但必要时可能会更改。)例如,将
int
3转换为
char
会产生值3的
char
——表示具有不同的位数,但值相同。将其转换为
浮点
也会产生3,但表示它的位非常不同。将3千克转换为磅可以产生6.6磅-3千克和6.6磅是一样的。将一个指针转换为另一个指针类型会产生指向同一位置的指针……您似乎在寻找一个操作,该操作将表示
浮点的位放入
uint64\t
的低位32位。这不是一种转换。(一些不保留精确值的转换包括浮点到整数转换,将3.25转换为整数会产生3。这是一种不完美的转换,但该值会保留到可能的范围。转换−输入
float
和输出
uint64_t
的示例将有助于澄清您真正想要做的事情。您是否关心结果不能跨机器移植?“最右边”是指最低有效字节还是最高寻址字节?投票时不清楚需要什么。违反了C 2018 6.5 7:“一个对象只能通过具有以下类型之一的左值表达式来访问其存储值…”基本上,
i
是一个
uint64\u t
,但此代码以
浮点
的形式访问它,而不是6.5 7中列出的类型之一。有些编译器支持它,我喜欢在有用的时候使用编译器扩展和非标准C,但在这种情况下没有必要使用它,因为有一些简单的可移植方法可以实现这个目标,比如另一个答案中显示的
memcpy
,或者使用联合(标准C支持,但C++不支持)。此外,另一个答案显示了如何将位移动到所需的低32位,而不会出现端性问题。尽管此答案指出endianness可能是一个问题,但如果输入的答案无法提供另一个答案中已提供的功能,并且需要启动可移植代码,那么该答案有什么价值?此代码还可能根据以下情况调用未定义的行为:“指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针与引用的类型未正确对齐,则行为未定义。“当您运行类似代码时,某些实现将抛出
SIGBUS
或类似的命令。