C 在同一条线上铸造两次
我在项目中看到了这段代码C 在同一条线上铸造两次,c,casting,C,Casting,我在项目中看到了这段代码 b的类型为void*: void *b = ...; int a = (int) (unsigned long) b; 这句话毫无意义吗?我的意思是,它在所有情况下都与a=(int)b相同?这可能避免了64位Unix系统上的编译器警告,其中unsigned long是一个64位的量,因此足以容纳指针,但int是一个32位的量,不足以容纳指针。转换为(无符号长)保留地址的所有位;随后对int的强制转换将丢弃地址的高阶32位,但默认情况下不会得到警告 证明: int ma
b
的类型为void*
:
void *b = ...;
int a = (int) (unsigned long) b;
这句话毫无意义吗?我的意思是,它在所有情况下都与
a=(int)b
相同?这可能避免了64位Unix系统上的编译器警告,其中unsigned long
是一个64位的量,因此足以容纳指针,但int
是一个32位的量,不足以容纳指针。转换为(无符号长)
保留地址的所有位;随后对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位编译
推测“地址的一部分”值将做什么很有趣。我在我的项目中也看到了这一点 在我的例子中,“b”的内容由用于进程间通信的其他源/中间件填充 填充“b”后,程序将获得“b”的内容,并将其转换为正确的字段“a”。然后,应用程序使用“a”进行处理
但是,我的项目使用char*而不是void*。直接将类型转换为指向较小类型(例如int)的指针可能会导致x64位环境下的某些编译器(如Clang)出现编译错误 例如:
void *p = GetSomeAddress;
int i = (int)p; //error on compilers like Clang.
解决办法是:
int i = (int)(unsigned long)p;
或
这是因为,在Unix上,在LP64模型下,long是64位的
在这种情况下,您需要彻底了解为什么需要从指针转换为int或其他可能导致数据丢失的较小类型
这个问题也可能对你有所帮助。
请注意,有创造力的人在
void*
s:)中隐藏数字(或布尔值)信息,这会让我有创造力吗?用我在你评论时编写的示例代码?呵呵,确实如此,因此+1:)认真地说,许多API使用void*
,其中intptr\u t
是合适的,许多API使用void*
,其中使用API的程序员最好使用不透明结构类型:外部结构不透明*xyz\u创建(int);外部无效xyz_自由(结构不透明*)代码>。如果用void*
替换struct opaque
,任何旧指针都可以传递到xyz_free()
函数,但是使用struct opaque
,不能只传递任何旧指针到它。+1因为有创意:)也许应该提到原始代码中的另一个问题,也就是说,从无符号类型到有符号类型的转换是由实现定义的。此外,在示例代码中,不需要对int
进行两次强制转换。
int i = (int)(long)p;