簡體   English   中英

如何將一個* signed * 24位int存儲到另一個變量中?

[英]How to store a *signed* 24 bit int into another variable?

我需要將24位整數編碼為32位int的末尾。

(第一個字節包含其他數據,其他三個字節為24位int使用為空)

我已經有一個SET_BYTE宏,並且可以成功地對無符號的 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 ), int8_t得到以下字節值:

-22
-1
-1

讀回這些內容(如果我在閱讀時執行<<0<<8<<16 ):

-22
-256
-65536

我假設我只需要完全避免帶符號值的這些偏移,但是我不確定什么是正確的方法?

如果需要≥32位的結構(如您所說,最后一個字節中還有其他數據),請使用struct位域:

struct Packed
{
    uint8_t byte;
    int32_t smaller : 24;
};

或者,您可以濫用std::bitset

struct fake_int24_t
{
    static_assert(sizeof(int) <= sizeof(unsigned long long), "");

    bitset<24> data;

    operator int() const {
        return data.to_ulong() - (1 << 23);
    }

    fake_int24_t& operator=(int val) {
        assert(val >= -(1 << 23)); // 2's complement
        assert(val < (1 << 23));

        data = bitset<24>(val + (1 << 23));

        return *this;
    }
};

現場演示

sizeof(fake_int24_t)不必為3,因此您可能需要在其中粘貼一個普通整數。

將24位整數編碼為32位int的末尾。

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的字節序,也不知道其編碼(2,1或正負號)。 事實證明,我們不需要該信息。

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;
}

我會在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;

(警告:未經測試)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM