簡體   English   中英

理解類型轉換(指針)

[英]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.

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