【发布时间】:2013-06-18 15:54:58
【问题描述】:
我在项目中看到了这段代码。
b的类型是void*:
void *b = ...;
int a = (int) (unsigned long) b;
这条线没有意义吗?我的意思是,在所有情况下都与a = (int) b 相同?
【问题讨论】:
我在项目中看到了这段代码。
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 位编译。
推测“地址的一部分”值会做什么是很有趣的。
【讨论】:
void*s 中 :)
void*,而 intptr_t 本来是合适的
void *,使用该 API 的程序员最好使用不透明的结构类型:extern struct opaque *xyz_create(int); extern void xyz_free(struct opaque *);。如果将struct opaque 替换为void *,则可以将任何旧指针传递给xyz_free() 函数,但使用struct opaque,则不能将任何旧指针传递给它。
int 进行两次强制转换。
在 x64 位环境下,直接类型转换为指向较小类型 say 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 或其他可能导致数据丢失的较小类型。
这个问题也可能对您有所帮助。 How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?
【讨论】:
我在我的项目中也看到了这一点。
就我而言,“b”的内容由用于进程间通信的其他源/中间件填充。
一旦填充了“b”,程序将通过强制转换获取“b”的内容到正确的字段“a”。然后应用程序使用“a”进行处理。
我的项目使用 char* 而不是 void*。
【讨论】: