为什么sockaddr_in*可以直接转换成sockaddr*

问题

最近在写Ethernet通讯相关的代码时发现bind()和accept()这些函数接受的是sockaddr*,但是咱定义的结构体是sockaddr_in类型的,一般都是在传入参数的时候加上(struct sockaddr *)显示转换就可以了。但是为什么不同结构体类型的指针可以之间转换呢?

答案(大概吧)

sockaddr_in和sockaddr是并排结构,指向sockaddr_in结构的指针也可以指向sockraddr结构并替换。

可以看见两者的结构分别为(不同地方定义可能不一样):


struct sockaddr {
	unsigned char	sa_len;
	unsigned char	sa_family;
	char	sa_data[14];
};

struct in_addr {
	unsigned long	s_addr;
};

struct sockaddr_in
{
	unsigned char	sin_len;
	unsigned char	sin_family;
	unsigned short	sin_port;
	struct in_addr	sin_addr;
	char	sin_zero[8];
};

可以看见两者的前面两项内容都是一样的。因此直接转换指针类型之后函数依然可以正确检索到前面重合的内容。

相关函数在实际操作过程中可以通过family项来判断整个结构体的实际长度,从而转换回正确的类型进行操作。

这也是为什么在使用这些函数的时候需要输入结构体的长度。假如函数转换得到的结构体长度与我们输入的长度不匹配,就报错了。

发表评论

您的电子邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据