![](/img/trans.png)
[英]What's the difference between sockaddr, sockaddr_in, and sockaddr_in6?
[英]casting between sockaddr and sockaddr_in
我遇到了一個套接字編程教程,引用它
“指向struct sockaddr_in的指針可以轉換為指向struct sockaddr的指針, 反之亦然 ”
我不明白如何將sockaddr_in投射到sockaddr。 將Big類型的指針強制轉換為Small類型應該給出UD行為。
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
struct sockaddr_in {
short int sin_family; // Address family, AF_INET
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Same size as struct sockaddr
};
演員如何不被定義? 把它們互相投射不是不安全嗎?
如果我有A級只有兩個整數而B級有4個整數。 如果我有一個類型B的指針,我將其轉換為A類型,那么我確定我可以獲取前兩個元素。 但是,如果類A首先聲明了2個字符並且稍后聲明了2個字符,則指針將無法正確獲取值,因為在這種情況下對象布局將是不同的。
編輯1:
class Anu
{
public:
char a;
int b;
Anu()
{
a='a';
}
};
class Anurag
{
public:
Anurag() { a=4;}
int a;
int b;
int c;
int d;
};
int main()
{
Anu objanu;
Anurag objanurag;
Anurag *ptrAnurag= &objanurag;
ptrAnurag= (Anurag*)&objanu;
cout<<ptrAnurag->a; //Some weird value here
return 0;
}
假設我通過調整變量類型來更改示例以使兩個類具有相同的大小...即使大小保持不變,對象布局仍然可能不同。
我將添加到@gsamaras的答案中說,未定義的行為並不總是意味着壞事即將發生。 未定義的行為實際上表示“我們*不提供任何關於XYZ發生時應該發生什么的規范”。
(* C ++標准)。
這是操作系統發生的地方,並說“它是由我們定義的”。
盡管通過標准sockaddr
不相關的結構( sockaddr_in
, sockaddr
)可能是未定義的行為,但OS API指定它對其API有效。
它們的大小相同 ,所以不,你沒有任何UB !
證明:
#include <stdio.h>
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
// src: http://www.gta.ufrj.br/ensino/eel878/sockets/sockaddr_inman.html
struct in_addr {
unsigned long s_addr; // load with inet_aton()
};
struct sockaddr_in {
short int sin_family; // Address family, AF_INET
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Same size as struct sockaddr
};
int main (void) {
printf("%zu\n", sizeof(unsigned short) + sizeof(char) * 14);
printf("%zu\n", sizeof(short int) + sizeof(unsigned short int) + sizeof(struct in_addr) + sizeof(unsigned char) * 8);
return 0;
}
輸出:
16
16
好評:sockaddr:2 + 14 = 16,sockaddr_in:2 + 2 + 4 + 8 = 16 - Amer Agovic
您可能還想看看這個問題: 為什么結構的sizeof不等於每個成員的sizeof之和?
請檢查這個問題: 是否可以將結構轉換為另一個?
我也在這里復制Benoit的答案:
這被稱為Punning類型 。 這里,兩個結構都具有相同的大小,因此不存在結構大小的問題。 雖然你幾乎可以將任何東西投射到任何東西上,但使用結構進行渲染很容易出錯。
還有Richard J. Ross III的這個:
這是C的“繼承”形式(注意引號)。 這是有效的,因為C不關心地址中的基礎數據,只是你所代表的。
該函數通過使用sa_family字段確定它實際上是什么結構,並將其強制轉換為函數內部的正確sockaddr_in。
不同的尺寸無關緊要。 就像您可以將不同長度的字符串傳遞給各種字符串處理函數一樣,您可以將不同長度的struct sockaddr
傳遞給各種套接字處理函數。
struct sockaddr
的大小由被調用函數根據結構的sa_family
成員的內容進行解釋。 另請注意,采用struct sockaddr *
地址的所有函數也采用socklen_t
參數來保存傳遞的結構的大小。
例如, struct sockaddr_un
結構是110字節:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
被調用的函數(如bind()
或getpeername()
具有類似的聲明
int getpeerame(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
由於各種插座結構的尺寸變化的原因。
注意每個struct sockaddr_???
的第一個成員struct sockaddr_???
是sa_family
。 因此,它總是在同一個地方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.