3

我对 C 中的类型转换有疑问:

void *buffer;

(int *)((int)buffer);

这种类型的铸造在做什么?做什么((int)buffer)

4

3 回答 3

5

想象一下,你在像我这样的 Linux/x86-64 计算机上。然后指针是 64 位并且int是 32 位宽。

因此,buffer变量已被初始化到某个位置;可能是 0x7fff4ec52020 (可能是某个局部变量的地址,可能是 inside main)。

演员表(int)buffer给你一个 int,可能是最低有效的 32 位,即 0x4ec52020

您再次使用 进行强制转换(int*)((int)buffer),这会为您提供虚假地址 0x000000004ec52020 ,该地址未指向有效内存。如果你取消引用那个虚假的指针,你很可能会得到一个 SIGSEGV。

所以在某些机器上(尤其是我的)(int *)((int)buffer)与;一样(int*)buffer

幸运的是,作为一个语句(int *)((int)buffer);它没有可见的副作用,并且会被编译器优化(通过“删除”它)(如果你要求它优化)。

所以这样的代码是一个巨大的错误(可能成为未定义的行为,例如,如果您取消引用该指针)。如果原始编码器真的想要这里描述的奇怪语义,他应该添加注释(这样的代码是不可移植的)!

也许#include-ing<stdint.h>和使用intptr_toruintptr_t可能更有意义。

于 2013-05-13T17:05:30.780 回答
2

让我们看看 C 标准是怎么说的。在 C11 标准的最新免费发布版本http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf的第 55 页上,我们有

5 整数可以转换为任何指针类型。除非前面指定,结果是实现定义的,可能没有正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。

6 任何指针类型都可以转换为整数类型。除非前面指定,结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。

这在您的示例中是什么意思?第 6 节说强制(int)buffer转换会编译,但如果整数不足以容纳指针(这可能在 64 位机器上),结果是未定义的。final(int*)转换为指针。

第 5 节说,如果整数大到足以容纳中间结果,则结果与从一开始就强制转换为 (int*) 完全相同。

简而言之,强制(int)转换充其量是无用的,最坏的情况是导致指针值丢失。

于 2013-05-13T17:27:50.353 回答
0

在直接的 C 代码中,这是没有意义的,因为到和从的转换void*是隐式的。以下将编译得很好

int* p = buffer;

更糟糕的是,这段代码可能会引入错误。考虑 64 位平台的情况。转换为int会将指针截断为 32 位,然后将其分配给int*. 这将导致指针值被截断并且肯定会导致错误。

于 2013-05-13T17:04:17.763 回答