这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int main (void) {
struct addrinfo hints;
memset (&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_CANONNAME;
struct addrinfo *res;
getaddrinfo ("example.com", "http", &hints, &res);
printf ("Host: %s\n", "example.com");
void *ptr;
while (res != NULL) {
printf("AI Family for current addrinfo: %i\n", res->ai_family);
switch (res->ai_family) {
case AF_INET:
struct sockaddr_in *sockAddrIn = (struct sockaddr_in *) res->ai_addr;
printf("Port number: %u\n", ntohs(sockAddrIn->sin_port));
printf("IP address is: %u\n", ntohs(sockAddrIn->sin_addr.s_addr));
break;
}
res = res->ai_next;
}
return 0;
}
行动中:
$ gcc ex3.c
$ ./a.out
主持人:example.com
用于当前addrinfo的AI系列:2
端口号:80
IP地址为:23992
AI系列用于当前 addrinfo:30
这一切都很好,但是这甚至都没有编译:
void *ptr;
while (res != NULL) {
printf("AI Family for current addrinfo: %i\n", res->ai_family);
switch (res->ai_family) {
case AF_INET:
ptr = (struct sockaddr_in *) res->ai_addr;
printf("Port number: %u\n", ntohs(ptr->sin_port));
printf("IP address is: %u\n", ntohs(ptr->sin_addr.s_addr));
break;
}
res = res->ai_next;
}
我要做的是向void
投射struct sockaddr_in *
指针。编译错误是:
ex3.c:33:48:错误:会员参考基础类型&#39; void&#39;不是一个 结构或联盟
printf("IP address is: %u\n", ntohs(ptr->sin_addr.s_addr));
我做错了什么?为什么指针ptr
没有投入?
答案 0 :(得分:4)
ptr
的类型为void *
,您需要在引用之前将转换添加到适当的类型。
回想一下:C不允许解除引用不完整的类型。根据C规范,void
是一个不完整的类型。
一个简单的解决方法是将ptr的类型更改为struct sockaddr_in *
。
您还可以在printf
行中添加强制转换,但这会给代码带来不必要的混乱。
答案 1 :(得分:4)
这一行:
ptr = (struct sockaddr_in *) res->ai_addr;
不按照你的想法行事;它不会自动使ptr
属于struct sockaddr_in *
类型,因此您仍尝试取消引用void
指针。你需要做的是
printf("Port number: %u\n", ntohs(((struct sockaddr_in *) res->ai_addr)->sin_port));
答案 2 :(得分:2)
为什么指针ptr没有投放?
cast
本身显然没有问题。问题是稍后在代码中使用void
指针ptr
。
在您的情况下,ptr
是指向void
类型的指针。与struct
指针相比,它没有任何类型信息。将带有cast
的指针放入void *
变量不会更改void *
变量本身的类型。它仍然是不完整类型,不能用作成员(de)引用运算符的操作数。
换句话说,void
类型不能包含成员,因此成员引用是完全错误的。
我认为ptr
void *
没有任何用处。也许,您想将ptr
定义为
struct sockaddr_in * ptr = NULL;
解决问题。
也就是说,%u
不是与uint16_t
类型一起使用的格式说明符(返回类型为ntohs()
)。您可能希望使用PRIu16
作为格式说明符。
答案 3 :(得分:2)
从
更改ptr的声明void * ptr;
到
sockaddr_in* ptr;
答案 4 :(得分:1)
ptr = (struct sockaddr_in *) res->ai_addr
;
这是你的错误。 ptr是一个void指针,你将为它指定一个struct指针。 因此,您必须首先创建一个结构指针,并将您的强制转换结果分配给that.Do
struct sockaddr_in *ptr;
ptr = (struct sockaddr_in *) res->ai_addr;