将指向较大结构的指针转换为指向较小结构的指针

标签 c sockets pointers casting struct

这篇文章将基于 this one 构建但会更通用一些。

我经常看到指向大型结构的指针被转换为指向较小结构的指针,我认为这是可行的,因为指针只是结构中第一个字节的地址。我仍然有一个问题是,当大多数方法没有指向它们期望的类型时,如何处理指针。

我将使用 Socket API 作为示例:

sockaddr_storage 大于 sockaddr,但指向 sockaddr_storage 的指针在传递之前会转换为指向 sockaddr 的指针类似于

的函数
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

因此,当指针指向比预期更大的结构时,函数往往会处理事情。他们说吗

“哦,传递给我的大小 (socklen_t addrlen) 比我想象的要大。最好将此指针转换回 sockaddr_storage!”

然后像这样访问其成员?或者他们做了更复杂的事情?

最佳答案

sockaddr 是 C 的穷人多态性习惯用法的完美示例。在面向对象语言中,sockaddr 将是一个基类,其中有多种协议(protocol)地址类型(sockaddr_insockaddr_in6sockaddr_ll 等)是“派生的”。

基本上,sockaddr 被定义为具有一个类型 (sa_family),该类型指定它真正保存的内容,后跟一些数据。指向 sockaddr 的指针通常指向派生结构 (sockaddr_*),它指定数据的特定解释。

sockaddr_storage 与普通 sockaddr 类似,因为它不保存特定的协议(protocol)地址,仅保存存储空间。不同之处在于 sockaddr_storage 指定的空间比 sockaddr 更多,使其成为存储特定于协议(protocol)的 sockaddr 的合适类型。

查看普通 sockaddr 的函数首先查看 sa_family,例如AF_INET(对于 IPv4)或 AF_INET6(对于 IPv6)或其他内容,然后将其赋予的指针强制转换为适当的 sockaddr 子类型(例如 IPv4 的 sockaddr_in)。然后它可能会检查addrlen以确保转换的指针指向足够的空间来容纳子类型。

关于将指向较大结构的指针转换为指向较小结构的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16026775/

相关文章:

c - 32 位和 64 位 c 数据类型的不同大小

C:从后台线程返回异步错误的模式?

c++ - C/C++ 从字符缓冲区读取以填充结构

sockets - JeroMQ 正确关闭

C 中将 char 数组转换为 void * 指针

C++ 将方法指针作为模板参数传递

python - 如何在编译时从 C 扩展模块检查 python API 的版本?

c# - 两个程序可以同时更新文本文件(实时通信)吗?

javascript - socket.io 和 vue.js 获取数据

c - 错误 C2446 : '==' : no conversion from 'int *' to 'int'