Program not compiling after casting pointer

124 views Asked by At

Here is my code:

#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;
}

And in action:

$ gcc ex3.c
$ ./a.out
Host: example.com
AI Family for current addrinfo: 2
Port number: 80
IP address is: 23992
AI Family for current addrinfo: 30

This is all fine, however this does not even compile:

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;
}

What I am trying to do is to cast a void pointer to a struct sockaddr_in *. The compile error is:

ex3.c:33:48: error: member reference base type 'void' is not a structure or union

printf("IP address is: %u\n", ntohs(ptr->sin_addr.s_addr));

What am I doing wrong? Why is the pointer ptr not casted?

5

There are 5 answers

2
user4520 On BEST ANSWER

This line:

ptr = (struct sockaddr_in *) res->ai_addr;

does not do what you think it does; it doesn't automagically make ptr be of type struct sockaddr_in *, so you're still trying to dereference a void pointer. What you need to do is

printf("Port number: %u\n", ntohs(((struct sockaddr_in *) res->ai_addr)->sin_port));
9
Sourav Ghosh On

Why is the pointer ptr not casted?

There is apparently no issue with the casting itself here. The problem is the usage of the void pointer ptr later in the code.

In your case, ptr is a pointer to a void type. It does not have any type information, as compared to a struct pointer. Putting a pointer with casting into a void * variable does not change the type of the void * variable itself. It still remains an incomplete type, which cannot be used as an operand to member (de)reference operator.

In other words, a void type cannot have a member, so the member reference is outright wrong.

I don't see any use of making ptr a void *. Maybe , you want to define ptr as

 struct sockaddr_in * ptr = NULL;

to get around the issue.

That said, %u is not a format specifier to be used with a uint16_t type (return type of ntohs()). You may want to use PRIu16 as the format specifier.

4
Mohit Jain On

Type of ptr is void *, you need to add a cast to appropriate type before deferencing it.

Recall that: C does not allow dereferencing incomplete types. And void as per C specs is an incomplete type.

One simple fix is to change the type of ptr to struct sockaddr_in *.

You can also add cast in the printf line itself, but this will add unnecessary cluttering to the code.

7
justin.m.chase On

Change the declaration of ptr from

void * ptr;

to

sockaddr_in* ptr;
0
Jagath01234 On

ptr = (struct sockaddr_in *) res->ai_addr;

this is your error. ptr is a void pointer and you are going to assign a struct pointer to it. So you must first create a struct pointer and the assign the result from your cast to that.Do

struct sockaddr_in *ptr;
ptr = (struct sockaddr_in *) res->ai_addr;