簡體   English   中英

C ++:使用沒有位移的指針將unsigned char轉換為unsigned int

[英]C++: Unsigned Char to unsigned int using pointers without bit shifts

假設我有一個類型為unsigned char的C風格數組:

unsigned char * c = (unsigned char *) malloc(5000 * sizeof(unsigned char));
for(int i = 0; i < 5000; i++) 
    c[i] = (unsigned char) ((i >> (i%4 * 8)) & 0xFF);

假設我有一個指針偏移到一個開始4字節整數的位置:

// pseudo code
unsigned int i = c + 10; // 10 = pointer offset, let's say. 

如果我想用正確的號碼加載i ,我可以這樣做:

unsigned int i = (*(c+10) << 24) + (*(c+11) << 16) + (*(c+12) << 8) + (*(c+13));

但是我不應該以某種方式使用演員表來做到這一點嗎?

// pseudo code -- I haven't gotten this to work yet: 

int i = (unsigned int) (*((void *)(c+10));

// or maybe
int i = *((unsigned int*)((void *)(c+10)));

簡而言之,在C風格的字節數組中將四個字節轉換為unsigned int的最干凈,最有效的方法是什么?

正確的方法是使用memcpy:

unsigned int i;
std::memcpy(&i, c + offset, sizeof(unsigned int));

在支持未對齊變量訪問的體系結構(如x86-64)上,這將被優化為簡單的指針取消引用,但在不支持未對齊訪問的系統(例如ARM)上,它將正確地獲取值出。

例如,請參閱: https//gcc.godbolt.org/z/l5Px4G 在gcc for x86和arm之間切換編譯器,看看指令的不同之處。

如果您從某些外部源獲取數據,請記住字節序的概念。 您可能必須翻轉整數的字節以使值有意義。

不,你不應該。 將不是對象大小的倍數的偏移量添加到指向已分配對象的指針可能會導致平台無法取消引用的指針。 它根本不是指向unsigned int的指針。

在某些平台上,性能將是殘酷的。 在某些平台上,代碼會出錯。

無論如何,轉變和添加都非常清晰易懂。 演員陣容更加混亂,需要了解平台的字節順序。 所以你不是讓事情變得更好,更簡單,也更清晰。

但是我不應該以某種方式使用演員表來做到這一點嗎?

不,沒有任何演員可以保證工作。


請注意,整數有很多表示形式。 如何將字節數組轉換為整數對象取決於整數在數組中的表示方式。 例如,如果將整數轉換為字節數組並通過網絡發送,則無法知道接收計算機是否使用相同的表示形式。

一個考慮因素是如何表示負數。 幸運的是,2的補充是如此無處不在的表現,我們通常可以忽略它。 但在你的情況下,由於你正在轉換無符號整數,因此它更不重要。

更相關的考慮因素是字節字節序。

如果您知道該數組與執行該程序的CPU使用的表示相同,那么您可以使用std::memcpy復制字節:

unsigned int i;
static_assert(sizeof i == 4);
std::memcpy(&i, c + 10, sizeof i);

只要源數據具有相同的表示形式,無論CPU使用的字節順序如何,這都能正常工作。


你的建議(*(c+10) << 24) + ...是正確的(或者似乎是,我沒有徹底檢查)是否字節數組的表示是大端。 如果數組很少或有其他字節序,那么建議是錯誤的。

當通過網絡接收數據時,此方法很有用,因為它不依賴於與執行CPU相同的表​​示。

暫無
暫無

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

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