C ++将不同的数据类型打包成一个长变量

时间:2016-08-03 16:57:06

标签: c++ binary packing

我进入陷阱试图将一些变量打包成一个8字节长的变量。

基本上,我有一些具有小二进制大小的短项目,我需要将它们打包在一起发送到必须能够将其拆还的类中。

所以我做了以下事情:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned int dat1   = 25;  // 1 byte long max
unsigned int dat2   = 1;   // 4 bit long max
unsigned int dat3   = 100; // 2 byte long max
unsigned int dat4   = 200; // 4 byte long max
unsigned int dat5   = 2;   // 4 bit long max

然后我创建一个PACKAGE类型的变量,它是空的(0)

PACKAGE pack = 0;

我想使用二进制操作将变量抛入该包中,我这样做:

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5;

它的效果只有一半,我计算出必须得到包等于2526526262902525058的十进制值,或者

0010001100010000000001100100000000000000000000000000110010000010

作为二进制,然而我得到的是588254914,或者 00100011000100000000111011000010‬为二进制 这在某种程度上是正确的尾巴和头部,但中间部分在某处丢失了。

完成此操作后,我仍然要以某种方式提取数据。

2 个答案:

答案 0 :(得分:2)

我宁愿使用bitfield结构来表示此类型(也请使用uint64_t来确保可用的大小):

union PACKAGE {
    struct bits {
        uint64_t dat1 : 8;  // 1 byte long max
        uint64_t dat2 : 4;  // 4 bit long max
        uint64_t dat3 : 16; // 2 byte long max
        uint64_t dat4 : 32; // 4 byte long max
        uint64_t dat5 : 4;  // 4 bit long max
    };
    uint64_t whole; // for convenience
};

comments中所述,您甚至可以使用uint_least64_t数据类型,以确保您的目标支持它(因为uint64_t的可用性是当前c ++标准中的可选项):

union PACKAGE {
    struct bits {
        uint_least64_t dat1 : 8;  // 1 byte long max
        uint_least64_t dat2 : 4;  // 4 bit long max
        uint_least64_t dat3 : 16; // 2 byte long max
        uint_least64_t dat4 : 32; // 4 byte long max
        uint_least64_t dat5 : 4;  // 4 bit long max
    };
    uint_least64_t whole; // for convenience
};

答案 1 :(得分:1)

假设sizeof(unsigned int) != sizeof(unsigned long long),每个班次的左操作数是错误的类型。每个移位操作都被截断(可能为32位)。

尝试,例如:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned long long dat1   = 25;  // 1 byte long max
unsigned long long dat2   = 1;   // 4 bit long max
unsigned long long dat3   = 100; // 2 byte long max
unsigned long long dat4   = 200; // 4 byte long max
unsigned long long dat5   = 2;   // 4 bit long max

pack = (dat1 << 56) | (dat2 << 52) | (dat3 << 36) | (dat4 << 4) | dat5;

或:

typedef unsigned long long PACKAGE; // 8 byte (shows as _int64 in debug)
(sizeof returns '8')
unsigned int dat1   = 25;  // 1 byte long max
unsigned int dat2   = 1;   // 4 bit long max
unsigned int dat3   = 100; // 2 byte long max
unsigned int dat4   = 200; // 4 byte long max
unsigned int dat5   = 2;   // 4 bit long max

pack = ((PACKAGE)dat1 << 56) | ((PACKAGE)dat2 << 52) | ((PACKAGE)dat3 << 36) | ((PACKAGE)dat4 << 4) | (PACKAGE)dat5;

注意:好的,实际上,右手操作数大于左手类型大小的每个移位操作都以位为单位调用未定义的行为。典型的未定义行为是截断,但标准允许任何其他行为,包括全球热核战争。

相关问题