我在项目中看到了这段代码。
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 位环境下,直接将类型转换为指向较小类型的指针,比如 int,可能会导致某些编译器(如 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*。