I saw this code in project.
b
's type is void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Is this line pointless? I mean, it this same as a = (int) b
in all cases?
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With