程序在转换指针

时间:2015-06-09 07:38:13

标签: 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; 
  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没有投入?

5 个答案:

答案 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;