C++ 将不同的数据类型打包到一个 long 变量中
C++ packing different data types into one long variable
我陷入了一个陷阱,试图将几个变量打包成一个 8 字节长的变量。
基本上,我有几个二进制文件较小的短项目,我需要将它们打包在一起发送到 class,它必须能够将其解压回来。
所以我做了以下内容:
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;
它仅适用于 half-good,我计算出我必须得到等于 2526526262902525058
或
的包的十进制值
0010001100010000000001100100000000000000000000000000110010000010
作为二进制,但是我得到的是 588254914
,或者
00100011000100000000111011000010
为二进制
它的尾巴和头部在某种程度上是正确的,但中间部分某处丢失了。
完成后,我仍将以某种方式提取数据。
假设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;
注意:好的,实际上每个右手操作数大于左手类型大小的移位操作,以位为单位调用未定义的行为。典型的未定义行为是截断,但标准允许任何其他行为,包括全球热核war。
我宁愿使用 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
};
如 you could even use the 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
};
我陷入了一个陷阱,试图将几个变量打包成一个 8 字节长的变量。
基本上,我有几个二进制文件较小的短项目,我需要将它们打包在一起发送到 class,它必须能够将其解压回来。
所以我做了以下内容:
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;
它仅适用于 half-good,我计算出我必须得到等于 2526526262902525058
或
0010001100010000000001100100000000000000000000000000110010000010
作为二进制,但是我得到的是 588254914
,或者
00100011000100000000111011000010
为二进制
它的尾巴和头部在某种程度上是正确的,但中间部分某处丢失了。
完成后,我仍将以某种方式提取数据。
假设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;
注意:好的,实际上每个右手操作数大于左手类型大小的移位操作,以位为单位调用未定义的行为。典型的未定义行为是截断,但标准允许任何其他行为,包括全球热核war。
我宁愿使用 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
};
如 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
};