15

我在项目中看到了这段代码。

b的类型是void*

void *b = ...;
int a = (int) (unsigned long) b;

这条线没有意义吗?我的意思是,a = (int) b在所有情况下都一样吗?

4

3 回答 3

25

这可能避免了 64 位 Unix 系统上的编译器警告,其中unsigned long64 位数量因此大到足以容纳指针,但int32 位数量不足以容纳指针。转换为(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 位编译。

推测将使用“地址的一部分”值做什么是很有趣的。

于 2013-06-18T05:23:17.453 回答
1

在 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' 失去精度”?

于 2013-06-18T06:04:35.050 回答
0

我在我的项目中也看到了这一点。

就我而言,“b”的内容由用于进程间通信的其他源/中间件填充。

一旦填充了“b”,程序将获取“b”的内容,并将其转换为正确的字段“a”。然后应用程序使用“a”进行处理。

我的项目使用 char* 而不是 void*。

于 2013-06-18T05:29:42.920 回答