[英]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
所以我想得到兩個分別具有1090
和0
值的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.