C++ 如何将*有符号*24位整数存储到另一个变量中?
我需要将一个24位整数编码到32位整数的末尾 第一个字节包含其他数据,其他三个字节为空,供24位int使用 我已经有一个SET_字节宏,我可以成功地对无符号24位值执行以下操作:C++ 如何将*有符号*24位整数存储到另一个变量中?,c++,c,bit-manipulation,C++,C,Bit Manipulation,我需要将一个24位整数编码到32位整数的末尾 第一个字节包含其他数据,其他三个字节为空,供24位int使用 我已经有一个SET_字节宏,我可以成功地对无符号24位值执行以下操作: SET_BYTE(DEST, START_BYTE_INDEX, (uint8_t)(VALUE)); SET_BYTE(DEST, START_BYTE_INDEX+1, (uint8_t)(VALUE >> 8)); SET_BYTE(DEST, START_BYTE_INDEX+2, (uin
SET_BYTE(DEST, START_BYTE_INDEX, (uint8_t)(VALUE));
SET_BYTE(DEST, START_BYTE_INDEX+1, (uint8_t)(VALUE >> 8));
SET_BYTE(DEST, START_BYTE_INDEX+2, (uint8_t)(VALUE >> 16));
我一直坚持的是,我不太确定如何修改这种方法来处理有符号的24位整数
例如,如果我尝试存储值-22,并将上面的修改为使用int8_t,显然,我会得到以下字节值:
-22
-1
-1
如果你需要一个≥32位结构正如您所说,在最后一个字节中有其他数据使用结构位字段:
struct Packed
{
uint8_t byte;
int32_t smaller : 24;
};
或者,您可以滥用:
sizeoffake\u int24\u t不必是3,因此您可能希望在其中插入一个正常整数。我将在24位部分使用符号大小表示:
int value = -22;
unsigned long target = std::abs(value) & ((1 << 23) - 1);
if (value < 0)
target |= 1 << 23;
要提取该值,只需颠倒过程:
int result = target & ((1 << 23) - 1);
if (target & (1 << 23))
result = -result;
警告:未测试
将24位整数编码到32位整数的末尾
OP的现有宏意味着24位无符号类型存储在little endian中-请参见下文。
假设24位有符号使用相同的尾数和公共2的补码整数编码
SET_BYTE(DEST, START_BYTE_INDEX, (uint8_t)(VALUE));
SET_BYTE(DEST, START_BYTE_INDEX+1, (uint8_t)(VALUE >> 8));
...
请注意,我们不知道32位int的endian,也不知道它的编码2、1或sign-mag。事实证明,我们不需要这些信息
struct signed_24_bit {
uint8_t other_data;
uint8_t use_by_the_24_bit_int[3];
};
int decode_24_bit_integer(struct signed_24_bit x) {
int32_t y = x.use_by_the_24_bit_int[0] // 1st byte of int24
+ (x.use_by_the_24_bit_int[1] * 0x100)
+ (x.use_by_the_24_bit_int[2] * 0x10000);
// If y > INT24_MAX
if (y > 0x7FFFFF) y -= 0x1000000;
return y;
}
// Assume `x` is in range of `int24_t`
struct signed_24_bit encode_24_bit_integer(int x) {
if ( x < 0) x += 0x1000000;
struct signed_24_bit y = { 0, { x, x/0x100, x/0x10000 } };
return y;
}
这个问题应该用C或C++来标记,而不是两者都可以。这两种方法的答案是不同的。最简单的方法是先左移8位,然后右移8位,然后24位带符号整数将符号扩展到32位。然而,根据C标准,这种方法可能是无效的。类似的解决方案是1将24位有符号整数转换为32位无符号整数,然后左移8位,然后转换为32位有符号整数,然后右移8位。这避免了UB,但需要有符号数为2的补码来得到期望的结果。@ C650我既使用C++又使用C外部,所以适用于ME的答案对My都是有用的,即位字段是实现所请求的行为的最简单的方法。我之所以避免这个特性是因为我认为它是针对C99的。我不知道它也是有效的C++,我可以使用比特集并记住这个方法,但是,是的,比特字段是超级容易理解的。comparison@c650如果发布的SET_BYTE的endian定义了所需的endian,位字段可能没有匹配的endian。然而,如果int-size、endian和对齐问题不把它搞砸的话,一个位字段是很有意义的。
SET_BYTE(DEST, START_BYTE_INDEX, (uint8_t)(VALUE));
SET_BYTE(DEST, START_BYTE_INDEX+1, (uint8_t)(VALUE >> 8));
...
struct signed_24_bit {
uint8_t other_data;
uint8_t use_by_the_24_bit_int[3];
};
int decode_24_bit_integer(struct signed_24_bit x) {
int32_t y = x.use_by_the_24_bit_int[0] // 1st byte of int24
+ (x.use_by_the_24_bit_int[1] * 0x100)
+ (x.use_by_the_24_bit_int[2] * 0x10000);
// If y > INT24_MAX
if (y > 0x7FFFFF) y -= 0x1000000;
return y;
}
// Assume `x` is in range of `int24_t`
struct signed_24_bit encode_24_bit_integer(int x) {
if ( x < 0) x += 0x1000000;
struct signed_24_bit y = { 0, { x, x/0x100, x/0x10000 } };
return y;
}