簡體   English   中英

將 uint8_t* 緩沖區轉換為 uint16_t 並更改字節順序

[英]Converting uint8_t* buffer to uint16_t and changing endianness

我想處理外部圖書館提供的數據。

lib 保存數據並提供對它的訪問,如下所示:

const uint8_t* data;
std::pair<const uint8_t*, const uint8_t*> getvalue() const {
  return std::make_pair(data + offset, data + length);
}

我知道當前數據包含兩個uint16_t數字,但我需要更改它們的字節順序。 所以總共數據是 4 個字節長並且包含這些數字:

66 4 0 0

所以我想得到兩個分別具有10900值的uint16_t數字。

我可以做基本的算術並在一個地方改變字節順序:

pair<const uint8_t*, const uint8_t*> dataPtrs = library.value();
vector<uint8_t> data(dataPtrs.first, dataPtrs.second);

uint16_t first = data[1] <<8 + data[0]
uint16_t second = data[3]<<8 + data[2]

但是我想做一些更優雅的事情(如果有更好的方法獲取uint16_t ,向量是可替換的)。

我怎樣才能更好地從uint8_t*創建uint16_t 如果可能的話,我會避免使用 memcpy,並使用更現代/更安全的東西。

Boost 有一些很好的 header-only endian 可以工作,但它需要一個uint16_t輸入。

為了更進一步,Boost 還提供了用於更改字節順序的數據類型,因此我可以創建一個結構:

struct datatype {
    big_int16_buf_t     data1;
    big_int16_buf_t     data2;
}

是否可以安全地(填充、平台依賴性等)將有效的 4 字節長uint8_t*轉換為datatype 也許有像這個聯盟這樣的東西?

typedef union {
    uint8_t u8[4];
    datatype correct_data;
} mydata;

也許有像這個聯盟這樣的東西?

否。在 C++ 中沒有很好地定義聯合類型雙關語。

這將在假設big_int16_buf_t的情況下起作用,因此datatype可以簡單地復制:

datatype d{};
std::memcpy(&d, data, sizeof d);
 uint16_t first = data[1] <<8 + data[0] uint16_t second = data[3]<<8 + data[2]

但是我想做一些更優雅的事情

這實際上(主觀上,在我看來)是一種非常優雅的方式,因為它在所有系統上都以相同的方式工作。 這會將數據讀取為小端,無論 CPU 是小端、大端還是其他端。 這很好攜帶。

但是我想做一些更優雅的事情(如果有更好的方法來獲取 uint16_ts,向量是可替換的)。

矢量似乎完全沒有意義。 你也可以使用:

const std::uint8_t* data = dataPtrs.first;

我怎樣才能更好地從uint8_t*創建uint16_t

如果您確定uint8_t指針后面的數據確實是uint16_t ,則 C++ 允許: auto u16 = *static_cast<uint16_t const*>(data); 否則,這是 UB。

給定大端值,將其轉換為小端值可以使用ntohs function(在 linux 下,其他操作系統具有類似功能)。


但請注意,如果您持有的指針指向兩個單獨的uint8_t值,則不得通過指針轉換來轉換它們。 在這種情況下,您必須手動指定哪個值去哪里(可以想象使用 function 模板)。 這將是最可移植的解決方案,而且編譯器很可能會根據 shifts 和 ors 創建高效的代碼。

暫無
暫無

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

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