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;