我对C:
中的类型转换有疑问void *buffer;
(int *)((int)buffer);
这种类型的铸造做什么?以及((int)buffer)
做了什么?
答案 0 :(得分:5)
想象一下,你和我一样在Linux / x86-64计算机上。那么指针是64位,int
是32位宽。
因此,buffer
变量已初始化为某个位置;也许是0x7fff4ec52020(可能是某个局部变量的地址,也许在main
内)。
转换(int)buffer
给你一个int,可能是最不重要的32位,即0x4ec52020
您正在使用(int*)((int)buffer)
再次投射,它会为您提供虚假地址0x000000004ec52020,它不会指向有效内存。如果你取消引用那个虚假的指针,你很可能会得到一个SIGSEGV。
所以在某些机器上(特别是我的)(int *)((int)buffer)
与(int*)buffer
不一样;
幸运的是,作为语句,(int *)((int)buffer);
没有明显的副作用,并且会被编译器优化(通过“删除”它)(如果你要求它进行优化)。 / p>
所以这样的代码是一个巨大的错误(可能会变成undefined behavior,例如,如果你取消引用那个指针)。如果原始编码器确实想要这里描述的奇怪语义,他应该添加注释(这样的代码是不可移植的)!
或许#include
- 使用<stdint.h>
并使用intptr_t
或uintptr_t
可能更有意义。
答案 1 :(得分:2)
让我们看看C标准的内容。在上一个自由发布的C11标准http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf版本的第55页,我们有
5整数可以转换为任何指针类型。除非事先指明,否则 结果是实现定义的,可能没有正确对齐,可能不指向 引用类型的实体,可能是陷阱表示。
6任何指针类型都可以转换为整数类型。除非事先指明,否则 结果是实现定义的。如果结果无法以整数类型表示, 行为未定义。结果不必在任何整数的值范围内 类型。
这在你的例子中意味着什么?第6节说转换(int)buffer
将编译,但如果整数不足以容纳指针(可能在64位机器上),结果是未定义的。最后的(int*)
会转回指针。
第5节说如果整数 大到足以保存中间结果,那么结果与从一开始就转换为(int *)的结果完全相同。
简而言之,强制转换(int)
最多是无用的,最坏的情况会导致指针值丢失。
答案 2 :(得分:0)
在直接C代码中,这是毫无意义的,因为来自void*
的转换是隐含的。以下将编译得很好
int* p = buffer;
更糟糕的是,此代码可能会引入错误。考虑64位平台的情况。转换为int
会将指针截断为32位,然后将其分配给int*
。这将导致指针值被截断并且肯定会导致错误。