我遇到了一个套接字编程教程,其中引用了
“指向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;
}
假设我通过调整变量类型来更改示例以使两个类具有相同的大小...即使大小保持不变,对象布局仍然可能不同。
答案 0 :(得分:4)
我将添加到@gsamaras的回答说,未定义的行为并不总是意味着坏事即将发生。未定义的行为实际上表示&#34;我们*不提供任何关于XYZ发生时应该发生什么的规范&#34;。
(* C ++标准)。
这是操作系统发生的地方并说“#34;它由我们定义&#34;。
虽然通过标准将未关联的结构(sockaddr_in
,sockaddr
)置于未定义的行为,但OS API指定它对其API有效。
答案 1 :(得分:1)
它们大小相同,所以不,你没有得到任何 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
您可能还想看一下这个问题:Why isn't sizeof for a struct equal to the sum of sizeof of each member?
请检查此问题:Is it possible to cast struct to another?
我也在这里复制Benoit的答案:
理查德·J·罗斯三世也是如此:这被称为Type Punning。这里,两个结构都具有相同的大小,因此不存在结构大小的问题。虽然你几乎可以将任何东西投射到任何东西上,但使用结构进行渲染很容易出错。
这是C的“继承”形式(注意引号)。这是有效的,因为C不关心地址中的基础数据,只是你所代表的数据。
该函数通过使用sa_family字段确定它实际上是什么结构,并将其转换为函数内正确的sockaddr_in。
答案 2 :(得分:1)
不同尺寸并不重要。就像您可以将不同长度的字符串传递给各种字符串处理函数一样,您可以将不同长度的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_???
的第一个成员是sa_family
。因此,它总是在同一个地方。