[英]Type casting struct pointer
我正在嘗試進行Socket編程,並在https://www.tenouk.com/Module43a.html上遇到了一篇文章,由於將char數組如何轉換為結構指針,我很難理解
char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
//some code here
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
根據我的理解,指針ip現在將保存緩沖區的地址,而struct ipheader成員的值現在將存儲在緩沖區中。 請幫助理解相同的。 如果我是對的,那我們將如何打印存儲在緩沖區中的值?
您的理解是正確的。 指針* ip將指向緩沖區。 char buffer [PCKT_LEN]是一個大小為sizeof(char)* PCKT_LEN的數組。 由於char通常為1個字節長,因此它只是PCKT_LEN個字節的內存塊。 PCKT_LEN定義為8192
存儲一個struct ipheader所需的字節數比這少得多。 嘗試int a = sizeof(ipheader)
和使用調試器看分配給值a
。 對我來說,它是24個字節,但是對您來說可能略有不同。 這意味着緩沖區可以容納的數據超過了struct ipheader所需的數據。 我沒有深入研究代碼,對套接字編程也不太了解。 但是,這樣做的一種用途可能是在結構外部添加額外的數據來增加緩沖區。 因為您知道struct ipheader占用了sizeof(ipheader)個字節,所以您將獲得sizeof(char)* 8192-剩下的sizeof(ipheader)可以增加數組。
編輯:Upun進一步檢查,這是正在發生的事情:
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
它嘗試將ip標頭存儲在緩沖區的開頭,然后使用udp標頭擴展該緩沖區。 通過使用buffer + sizeof(struct ipheader)
它通過將buffer + sizeof(struct ipheader)
偏移sizeof(struct ipheader)個字節來確保它在 ipheader 之后存儲udp頭。 基本上struct ipheader *ip
指向緩沖區的開頭,而struct udpheader *udp
指向buffer + sizeof(struct ipheader)
。 我希望這是有道理的。 顯然,緩沖區中還剩下很多空間,因此您可能會進一步擴大它。
如何將char數組轉換為struct指針
您不能安全地這樣做。 該代碼調用未定義的行為:
char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
//some code here
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
該代碼違反了嚴格的別名規則 。 基本上,這意味着不是某種對象類型的內存不能被視為該類型的對象,除了任何非char
對象都可以視為char
數組。
那不是發布的代碼中發生的事情。 在發布的代碼中,將char
數組視為是struct ipheader
。
內存不是一個struct ipheader
,而是一個char
數組,因此代碼違反了嚴格的別名。
從char *
到struct ipheader *
還可能導致對象對齊不正確並違反6.3.2.3指針第7段 :
指向對象類型的指針可以轉換為指向不同對象類型的指針。 如果結果指針未針對引用類型正確對齊,則該行為未定義。 ...
不幸的是,您在這里發現的代碼非常普遍,因為基於x86的計算機是程序員廣泛使用的最常見的平台,它們非常寬容錯位的訪問,因此此類代碼易於“工作”。
請參閱Linux中的結構分配在ARM上失敗,但在x86上成功在不起作用的平台上進行說明。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.