在同一条线上投两次
我在项目中看到了这段代码。
b
的类型是void*
:
void *b = ...; int a = (int) (unsigned long) b;
这条线是没有意义的吗? 我的意思是,它在所有情况下都与a = (int) b
相同吗?
这可能避免了64位Unix系统上的编译器警告,其中unsigned long
是64位数量,因此大到足以容纳指针,但int
是32位数量,不足以容纳指针。 转换为(unsigned long)
保留地址的所有位; 后续的int
抛出地址的高32位,但默认情况下不会收到警告。
展示:
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] $
在Mac OS X 10.8.4上使用GCC 4.7.1,默认为64位编译。
有趣的是推测将对“地址的一部分”值做什么。
直接类型转换为指向较小类型的指针,如果在x64位环境下,可能会导致某些编译器(如Clang)的编译错误。
例如:
void *p = GetSomeAddress; int i = (int)p; //error on compilers like Clang.
解决方案是:
int i = (int)(unsigned long)p;
要么
int i = (int)(long)p;
这是因为,在Unix上,在LP64模型下,long是64位。
在这种情况下,您需要彻底查看为什么需要从指向int或其他较小类型的类型转换,这可能导致数据丢失。
这个问题也可以帮到你。 在64位计算机上编译32位代码时,如何处理“从’void *’转换为’int’失去精度”?
我也在我的项目中看到了这一点。
对于我的情况,’b’的内容由用于进程间通信的其他源/中间件填充。
一旦’b’被填充,程序将获得’b’的内容,并将其转换为正确的字段’a’。 然后应用程序使用’a’进行处理。
我的项目使用char *而不是void *。