[英]How can I cast a 6 byte array into a numerical value?
通常可以從char* buf
檢索uint64_t
或uint32_t
/ uint16_t
等,如下所示:
uint32_t val = *(uint32_t*) buf;
但現在假設buf
是char [6]
,如何從中檢索數值?
*無符號大端(網絡字節順序)
一種便攜且符合標准的方式(與指針轉換或memcpy相反)將使其明確:
uint64_t val = 0;
for (int i = 0; i < 6; ++i)
val |= (uint64_t)(unsigned char)buf[i] << (8*(6-i-1));
這假設是大端(網絡字節順序)。 對unsigned char
的額外強制轉換是一個hack,如果你的輸入數組已經是unsigned char*
類型,你就不需要了。
使用uint64_t val = 0; memcpy(&val, buf, 6);
uint64_t val = 0; memcpy(&val, buf, 6);
但要注意字節序問題(這個問題適用於小尾數val和buf)。
避免丑陋演員的另一種方法是使用聯盟:
union {
uint64_t u64;
uint8_t c[8];
} foo;
將字節按正確順序寫入foo.c[]
,然后訪問foo.u64
。 不是100%ISO C Kosher,但在大多數現代C實現上都是正確的。
我不會問你是如何得到一個大端的六字節緩沖區。
const int odd_buffer_size = 6;
char src[ odd_buffer_size ] = { … };
uint64_t dst = 0;
// Copy the big-endian data into a big-endian long:
memcpy( ( (char*) & dst ) + 2, src, odd_buffer_size );
// Read the data as a value (aliasing-safe) and convert endianness:
dst = ntohll( dst );
ntohll
不是標准C,但可以在Windows中使用,有時在Linux上可用。 它的名稱似乎因平台而異(例如be64toh
),但有些設施始終可用。
順便說一句,技巧uint32_t val = *(uint32_t*) buf;
是不安全的,因為緩沖區可能(在這種特殊情況下,幾乎肯定是)不正確地對齊以訪問uint32_t
值。
即使用奇數地址形成類型為uint32_t *
的值也足以在C中崩潰。在重新解釋字節時,始終使用memcpy
或union
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.