user1825770
user1825770

Reputation: 359

warning: cast from pointer to integer of different size

I'm working on socket programming.. my code executes the way I want it to, I'm able to use it. BUT it gives me a warning on compilation.

I compile using

gcc server1.c -o server1 -lpthread

And I get the warning

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

This error comes for the following code

int newsockfd;
newsockfd = (int)newsockfdd; //this line

And I'm using newsockfdd (which is int) in the following chunk of code

if (pthread_create(&threadID[i++], NULL, serverThread, (void *)(intptr_t)newsockfdd) != 0)
    {
        perror("Thread create error");
    }

As you can probably tell, the code is not written too well (I am working on making it better). I know that this warning comes because of something to do with the size of int. But I really dunno how to fix it. Before I put in (intptr_t) in the pthread_create statement, it was showing a warning on that line, but that time the warning was

warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]

It seems like there should be a simple fix to this? But I can't find it. I'm using Ubuntu 64-bit. Is that a reason for the warning?

Upvotes: 4

Views: 19832

Answers (1)

Daniel Fischer
Daniel Fischer

Reputation: 183978

As has been established in the comments, the situation is (modulo renaming to avoid confusing occurrences of newsockfdd as passed argument or received parameter)

void *serverThread(void *arg) {
    // ...
    int newsockfd = (int)arg;
    // ...
}

and in main (or a function called from there)

// ...
int newsockfdd = whatever;
// ...
if (pthread_create(&threadID[i++], NULL, serverThread, (void *)(intptr_t)newsockfdd) != 0)
// ..

So when the int newsockfdd is passed as an argument to serverThread, it is cast to a void*. Originally, that cast was direct, but the intermediate cast to intptr_t was inserted to remove the warning about the cast to pointer from integer of different size.

And in serverThread, the received void* is cast to int, resulting in the warning about the cast from pointer to integer of different size.

That warning could probably also be removed by inserting an intermediate cast to intptr_t.

But, while the standard allows casting integers to pointers and vice versa, the results are implementation-defined and there's no guarantee that int -> void* -> int round-trips (although, a footnote in the standard says

The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.

so probably it will round-trip and work as intended in this case - but it would likely not work [only for values of small enough absolute value] if the size of a void* is smaller than that of the integer type [consider long long -> void* -> long long on 32-bit systems]).

The proper fix is to avoid the casting between integers and pointers,

void *serverThread(void *arg) {
    // ... check that arg isn't NULL
    int newsockfd = *(int *)arg;
    // ...
}

in severThread, cast the received pointer to a pointer of appropriate type, and read the pointed-to value, and in main

if// ...
int newsockfdd = whatever;
// ...
if (pthread_create(&threadID[i++], NULL, serverThread, &newsockfdd) != 0)

pass the address of newsockfdd.

One caveat: if serverThread is called from multiple places, the calls in all these places need to be fixed.

Upvotes: 6

Related Questions