将int转换为void指针并再次返回int是否安全?

时间:2010-08-25 16:22:46

标签: c++ c pointers

在C和/或C ++中:将int转换为void指针并再次返回int是否安全?

基于问题“C++: Is it safe to cast pointer to int and later back to pointer again?”。

8 个答案:

答案 0 :(得分:10)

在大多数现代普通机器中,可能。

但是,我敢打赌,有一些模糊的编译器或配置(例如,使用32位整数运算的16位寻址机器),情况并非如此。

uintptr_t保证同时包含两者,因此如果您愿意,请使用该类型。

答案 1 :(得分:3)

这是一个示例,在将整数转换为指针时,将指针转换为整数可能不会产生相同的指针。

给定一个具有24位地址并使用两个16位数量来描述位置的架构。让一个数量为SEGMENT,另一个为OFFSET。位置由符号SEGMENT:OFFSET指定。

实际的24位(物理)地址由以下公式计算:

address = segment * 16 + offset.

使用这种表示法,可以有多个描述相同物理地址的SEGMENT:OFFSET对。

转换为整数时,使用32位(无符号)数量(以简化处理器中的内部计算)。问题是如何将物理地址转换为在创建物理地址时使用的相同SEGMENT :: OFFSET。

将整数转换为指针的通用公式为:

offset = address & 0xFFFF; // Mask off high order bits, keep lower 16.
segment = address >> 16;   // Shift address right 16 bits, zero fill.

虽然这个新段的物理地址和偏移量等于原始SEGMENT:OFFSET的物理地址,但不保证段和偏移量是相同的。

为了优化代码,有一些处理器指令在段中使用相对寻址。当SEGMENT值因物理地址转换而发生变化时,这些指令可能会混乱。

在这种情况下,可以从指针转换为整数。但是,从整数到指针的转换是强烈的冒充。在运行时可能会发生难以调试的错误。

奖金问题:您能说出实际的架构吗?

答案 2 :(得分:2)

你为什么要这样做?

回复C,我对C ++的了解不够:不,没有定义行为将int强制转换为void*。首先,如果你有这样的话,你应该总是使用uintptr_t。使用int是一种滥用行为。

然后,如果您的uintptr_t不是来自有效地址,则C不保证任何内容。它只能保证反过来。不要这样做。

编辑:以下是C99标准的相关部分。正如您所看到的,所有警报都可以消失......

  

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

最后一个特别令人尴尬,因为这意味着这样获得的指针值不能再被使用,直到它被覆盖:

  

某些对象表示需要   不代表对象的值   类型。如果是对象的存储值   有这样的表示,并阅读   通过一个没有的左值表达式   有字符类型,行为是   未定义。 ......这样的表述是   称为陷阱表示

答案 3 :(得分:1)

没有。 void指针与大小的任何其他指针没有区别。因此,它将遇到与其他指针类型完全相同类型的问题。

答案 4 :(得分:1)

它的实现定义与最后一个问题一样,并且出于同样的原因。它不太可能导致不良行为,但仍然是实施定义。

答案 5 :(得分:1)

没有。可能在某些情况下,它似乎适用于某个编译器和设置,然后两年后,您花费数周时间调试某些内容发生了变化,转换不再按预期工作。

如果您只是以不需要这种行为的方式设计代码(最好的情况是避免使用这种转换,最坏情况下使用char[])那么您就不必担心未来会有一些模糊的错误。

答案 6 :(得分:0)

不一定。取决于指针的大小。你为什么要这样做?

答案 7 :(得分:0)

如果你的整数范围相当小,你总是可以这样做:

static const char dummy[MAXVAL];

然后使用dummy+i作为将i编码为指针的方法。这是100%便携式。如果你只关心它是99%的便携式,你可以使用(char *)0 + i