I saw this code in project.
b
\'s type is void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Is this line
Directly typecasting to pointer to smaller type say int may result in compilation error on some compiler (like Clang) under x64 bit environment.
For example:
void *p = GetSomeAddress;
int i = (int)p; //error on compilers like Clang.
Solution is:
int i = (int)(unsigned long)p;
or
int i = (int)(long)p;
This is because, on Unix, under LP64 model, long is 64-bit.
Such cases, you need to look thoroughly that why you need typecast from pointer to int or other smaller type which can result in loss of the data.
This question may also help you. How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?
This probably avoids a compiler warning on 64-bit Unix systems where unsigned long
is a 64-bit quantity and hence big enough to hold a pointer, but int
is a 32-bit quantity that is not big enough to hold a pointer. The cast to (unsigned long)
preserves all the bits of the address; the subsequent cast to int
throws away the high-order 32-bits of the address, but does so without getting a warning by default.
To demonstrate:
int main(void)
{
void *b = (void *)0x12345678;
int a = (int)(unsigned long)b;
int c = (int)b;
return a + c;
}
$ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c
ar.c: In function ‘main’:
ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
$
Using GCC 4.7.1 on Mac OS X 10.8.4, defaulting to 64-bit compilation.
It is interesting to speculate what will be done with the 'part of an address' value.
I see this in my project too.
For my case, the content of 'b' is populated by other sources/middleware used for inter-process communication.
Once 'b' is populated, the program will get the contents of 'b' with a cast to the correct field 'a'. the application then uses 'a' for processing.
My project uses char* instead of void* though.