[英]Understanding typecasting(pointers)
我正在閱讀 Beej 的網絡編程指南,但在理解某個函數時遇到了困難。 該函數需要一個char *
指針,但它取消引用該指針並將其轉換為 (unsigned long int) 並執行一些按位運算。 為什么我們不能將它作為(unsigned int *)
而不是(unsigned char *)
傳遞。 此外,如果參數被(void *)
替換,然后在代碼中我們做了一些類似的事情:
*(unsigned long int *)buf[0] << 24
我們會得到同樣的結果嗎? (抱歉,這是我第一次在這里提問,所以如果需要更多信息,請告訴我)。
unsigned long int unpacku32(unsigned char *buf)
{
return ((unsigned long int)buf[0]<<24) |
((unsigned long int)buf[1]<<16) |
((unsigned long int)buf[2]<< 8) |
buf[3];
}
你的建議不能保證有效。 除非buf
指向實際的unsigned long
,否則您試圖將一種類型的對象讀取為另一種不允許的(除非您讀取為unsigned char
)。 如果您創建的指針值與其類型不正確對齊,則可能會出現更多問題。
然后還有字節序的問題。 通過網絡發送的字節通常以大端格式發送,即最重要的字節在前。 如果您的系統是 little-endian,它將以相反的順序解釋字節。
您發布的函數演示了以符合標准的方式從字節緩沖區反序列化unsigned long
的正確方法。
這將使其依賴於平台的字節序。 所以我們從定義的順序中挑選出零件,使其平台中立。
buf[0]
被視為 8 位無符號值。 如果我們這樣做:
(unsigned long int)buf[0] << 24
,通過強制轉換,我們告訴我們不要將其視為 8 位值,而是將其視為 64 位,因此我們有更多空間可以使用。
我們只平移了buf[0]
, buf[1]
,其他字段在平移過程中不考慮。
如果你想轉換為unsigned long
可以說一個字符串"aabbccd"
並且我們不關心字節序,我們可以像下面這樣做:
char* str = const_cast<char *>("aabbccd\0");
unsigned long value = *(reinterpret_cast<unsigned long *>(str));
std::cout << value << std::endl;
std::cout << reinterpret_cast<char *>(&value) << std::endl;
應該指出的是, unsigned long
最多只能存儲 8 個字符,因為它是 64 位整數。 但是,如果許多平台要使用相同的數據,由於字節順序,這樣做可能還不夠。 你的書中給出的方法就像有人提到的平台中立。
該函數需要一個
char *
指針,但它取消引用該指針並將其強制轉換為 (unsigned long int
) 並執行一些按位運算。
實際上,代碼所做的是使用數組索引運算符從緩沖區中取出第一個字節,將其轉換為unsigned long int
,然后執行一些按位運算。 取消引用的指針是一個unsigned char *
與長整數無關。
為什么我們不能將它作為 (unsigned int *) 而不是 (unsigned char *) 傳遞。
因為它不是指向任何類型整數的指針。 它是一個指向unsigned char
緩沖區的指針,即字節。 將指針視為指向不同類型的指針可能會導致違反“嚴格別名規則”(我鼓勵您閱讀)。
此外,如果參數被 (void *) 替換,然后在代碼中我們做了一些像
*(unsigned long int *)buf[0] << 24
這樣的事情,我們會得到相同的結果嗎?
不。如果您將buf
定義為void*
,則buf[0]
是一個毫無意義的表達式。 如果buf
被定義為或強制轉換為unsigned long int *
,則buf[0]
是一個unsigned long int
,而不是算法所期望的unsigned char
。 幾乎肯定會設置太多位(多達 64,而不是 8)並且表達式的結果將無效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.