Reputation: 359
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
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