C 强制转换指针后程序未编译
这是我的密码:C 强制转换指针后程序未编译,c,pointers,C,Pointers,这是我的密码: #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; mems
#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;
}
我试图做的是将void
指针投射到*中的struct sockaddr\u。编译错误是:
ex3.c:33:48:错误:成员引用基类型“void”不是
结构或结合
printf("IP address is: %u\n", ntohs(ptr->sin_addr.s_addr));
我做错了什么?为什么指针ptr
未浇铸
为什么指针ptr没有浇铸
显然,这里的cast
ing本身没有问题。问题在于代码后面使用了void
指针ptr
在您的例子中,ptr
是指向void
类型的指针。与struct
指针相比,它没有任何类型信息。将带有cast
ing的指针放入void*
变量不会更改void*
变量本身的类型。它仍然是一个不完整的类型,不能用作操作数到成员(de)引用运算符
换句话说,void
类型不能有成员,因此成员引用是完全错误的
我看不出做ptr
avoid*
有什么用。也许,您想将ptr
定义为
struct sockaddr_in * ptr = NULL;
回避这个问题
也就是说,%u
不是与uint16\u t
类型一起使用的格式说明符(返回类型为ntohs()
)。您可能希望使用PRIu16
作为格式说明符。类型ptr
为void*
,您需要在延迟之前将强制转换添加到适当的类型
回想一下:C不允许取消对不完整类型的引用。根据C规范,void
属于不完整类型
一个简单的修复方法是在*
中将ptr的类型更改为struct sockaddr\u
您也可以在printf
行本身中添加强制转换,但这会给代码添加不必要的混乱。此行:
ptr = (struct sockaddr_in *) res->ai_addr;
不做你认为它做的事;它不会自动将*
中的ptr
类型设置为struct sockaddr\u,因此您仍在尝试取消引用void
指针。你需要做的是
printf("Port number: %u\n", ntohs(((struct sockaddr_in *) res->ai_addr)->sin_port));
将ptr的声明更改为
void * ptr;
到
ptr=(struct sockaddr_in*)res->ai_addr
这是你的错误。ptr是一个空指针,您将为其分配一个结构指针。
因此,您必须首先创建一个结构指针,并将强制转换的结果分配给该指针
struct sockaddr_in *ptr;
ptr = (struct sockaddr_in *) res->ai_addr;
这里是演员阵容:ptr=(struct sockaddr_in*)res->ai_addr;是的,但是ptr
的类型仍然是void
。那么这个代码做什么呢ptr=(struct sockaddr_in*)res->ai_addr?@KorayTugay将res->ai_addr
显式转换为(as)struct sockaddr_in*
,然后隐式转换为void*
,并分配给ptr。请注意,程序中变量的值可能会更改,但类型不会更改。下面是强制转换:ptr=(struct sockaddr_in*)res->ai_addr@KorayTugay演员阵容不会改变ptr
的类型,是吗?:-)@KorayTugay不多-将res->ai_addr
的值赋给ptr
,但ptr
的类型保持不变。@KorayTugay告诉我们如何解释res->ai_addr
作为指向中的结构sockaddr\u的指针,但ptr
保持void*
。但在本文中:一个答案是:void*会自动安全地升级为任何其他指针类型。这不是我要问的。你确定吗?看起来你是基于代码片段。是的,我确定。如果你愿意的话,看看斯祖尔西奥的回答。他说的和我说的一样:-/不,他没有。无论如何,谢谢。如果可以的话,再问一个问题。为什么是这个printf(“IP地址是:%u\n”,ntohs(sockAddrIn->sin_addr.s_addr));还在打印23992?我希望得到类似于120.32.3.2..@KorayTugay的两个问题-首先,ntohs
代表network to host short
-short意味着两个字节,就像端口一样。您需要ntohl
。第二,IPv4地址实际上是32位整数。要将其转换为十进制点表示法(我们已经习惯了),可以使用inet\u ntoa
,或者更好的方法是使用inet\u ntop
(尽管前者的语法更简单)。请注意,如果使用这些函数,则不需要将sin\u addr
转换为主机字节顺序,因为它们会为您处理该顺序。
sockaddr_in* ptr;
struct sockaddr_in *ptr;
ptr = (struct sockaddr_in *) res->ai_addr;