在同一条线上投两次

时间:2013-06-18 05:16:47

标签: c casting

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

b的类型为void*

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

这条线是否毫无意义?我的意思是,它在所有情况下与a = (int) b相同吗?

3 个答案:

答案 0 :(得分:22)

这可能避免了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位编译。

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

答案 1 :(得分:1)

直接将类型转换为指向较小类型的指针,例如int可能会导致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或其他较小类型的类型转换,这可能导致数据丢失。

这个问题也可以帮到你。 How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?

答案 2 :(得分:0)

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

对于我的情况,'b'的内容由用于进程间通信的其他源/中间件填充。

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

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