Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将*有符号*24位整数存储到另一个变量中?_C++_C_Bit Manipulation - Fatal编程技术网

C++ 如何将*有符号*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

我需要将一个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, (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;
}