这篇文章将以此为基础,但会更加通用。

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

我将以Socket API为例:

sockaddr_storagesockaddr但是指向sockaddr_storage指针在传递给类似函数之前先转换为指向sockaddr指针。

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

因此,当指针指向比预期更大的结构时,如何使用函数倾向于处理事情。 他们说

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

然后像这样访问它的成员? 还是他们做的事情更复杂?

===============>>#1 票数:3 已采纳

sockaddr是C的穷人多态习惯用法的完美示例。 在OO语言中, sockaddr将是一个基类,从中“派生”许多协议地址类型( sockaddr_insockaddr_in6sockaddr_ll等)。

基本上, sockaddr定义为具有类型( sa_family ),该类型指定其真正拥有的内容,然后是一些数据。 指向sockaddr的指针通常指向派生的结构( sockaddr_* ),该结构指定对数据的特定解释。

sockaddr_storage与普通的sockaddr相似,因为它不保存特定的协议地址,仅保存存储空间。 区别在于sockaddr_storage指定的空间比sockaddr更多,这使其成为存储特定于协议的sockaddr的合适类型。

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

===============>>#2 票数:1

@nneonneo对于套接字示例中发生的事情给出了很好的答案。

但是一般来说:

"What I still have a question about is how to most methods handle pointers when they aren't pointing at the type they expect."

重要的是它们是否接收到指向该函数计划与其进行匹配的结构的指针。 C为布局提供了一些保证,使之成为可能。 在那种情况下,函数确实获得了指向它们期望类型的指针。 只是在内存中有一些其他东西可以忽略。

通常,在调用的函数中没有downcast 它只是在较大结构的base class部分上运行

===============>>#3 票数:0

我的猜测是这些函数根本不在乎,如果所指向的结构比预期的要大,则至少不会产生访问冲突。 当然,较大结构的第一部分必须具有与较小结构相同的成员(类型),以便正确读取值。

不建议您在自己的代码中执行此操作,否则编译器会抱怨类型不兼容。

  ask by Matt Vaughan translate from so

未解决问题?本站智能推荐: