结构中的位顺序不是我期望的

时间:2019-06-04 07:24:54

标签: c++ endianness bit-fields

我有一个使用16位浮点数的框架,我想分离其组件,然后用于32位浮点数。在我的第一种方法中,我使用了移位和类似的方法,尽管这种方法有效,但是阅读却非常混乱。

然后我想改为使用自定义位大小的结构,并使用联合写入该结构。

重现该问题的代码:

#include <iostream>
#include <stdint.h>

union float16_and_int16
{
    struct
    {
        uint16_t    Mantissa : 10;
        uint16_t    Exponent : 5;
        uint16_t    Sign : 1;
    } Components;

    uint16_t bitMask;
};

int main()
{
    uint16_t input = 0x153F;

    float16_and_int16 result;
    result.bitMask = input;

    printf("Mantissa: %#010x\n", result.Components.Mantissa);
    printf("Exponent: %#010x\n", result.Components.Exponent);
    printf("Sign:     %#010x\n", result.Components.Sign);
    return 0;
}

在该示例中,我希望尾数为0x00000054,指数为0x0000001F,符号为0x00000001

相反,我得到的尾数:0x0000013f,指数:0x00000005,符号:0x00000000

这意味着从我的位掩码中首先提取符号(第一个位),然后是5位到指数,然后是10位到尾数,因此顺序与我想要的顺序相反。为什么会这样?

2 个答案:

答案 0 :(得分:5)

最糟糕的是,其他编译器可能会给出预期的顺序。该标准从未指定位域的实现细节,特别是顺序。通常的理由是,它是一个实现细节,程序员不应依赖也不依赖于此。

缺点是无法在跨语言程序中使用位域,并且程序员不能使用位域来处理具有众所周知位域的数据(例如在网络协议标头中),因为它太复杂了,无法确保实施将对其进行处理。

由于这个原因,我一直以为这只是一个无法使用的功能,我只对无符号类型而不是位域使用位掩码。但是最后一部分不过是我个人的看法...

答案 1 :(得分:2)

对于这个编译器,我会说您的input是不正确的。这就是float16_and_int16顺序的样子。

 sign   exponent  mantissa
 [15]   [14:10]    [9:0]

SGN |  E  X  P  O  N  E  N  T|     M  A   N   T   I   S   S   A                |
 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |

如果input = 0x153F,然后bitMask ==

SGN |  E  X  P  O  N  E  N  T|     M  A   N   T   I   S   S   A                |
 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
 0     0    0    1    0    1    0    1    0    0    1    1    1    1    1    1

如此

MANTISSA == 0100111111  (0x13F)
EXPONENT == 00101 (0x5)
SIGN == 0 (0x0)

如果您希望尾数为0x54,指数为0x1f且符号为0x1,则需要

SGN |  E  X  P  O  N  E  N  T|     M  A   N   T   I   S   S   A                |
 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
 1     1    1    1    1    1    0    0    0    1    0    1    0    1    0    0

input = 0xFC64