代码之家  ›  专栏  ›  技术社区  ›  Lesmana

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

  •  5
  • Lesmana  · 技术社区  · 16 年前

    在C和/或C++中,将int转换为空指针并再次返回int是安全的吗?

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

    8 回复  |  直到 15 年前
        1
  •  10
  •   Steven Schlansker    16 年前

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

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

    uintptr_t 不过,这两种类型都可以保证,因此如果您愿意,可以使用该类型。

        2
  •  3
  •   Thomas Matthews    16 年前

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

    给出一种具有24位地址并使用两个16位数量描述位置的体系结构。让一个量是段,另一个量是偏移量。位置由符号段:偏移指定。

    实际24位(物理)地址的计算方法如下:

    address = segment * 16 + offset.
    

    使用这个符号,可以有多个段:描述相同物理地址的偏移对。

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

    将整数转换为指针的一般公式是:

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

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

    为了优化代码,在一个段中有使用相对寻址的处理器指令。当段值由于从物理地址转换而改变时,这些指令可能会变得混乱。

    在这种情况下,可以将指针转换为整数。但是,强烈建议不要将整数转换为指针。在运行时可能会发生难以调试的错误。

    附加问题:你能说出实际的架构吗?

        3
  •  2
  •   Jens Gustedt    16 年前

    你为什么要这么做?

    对C的答复,我对C++的了解不多:不,没有定义行为来抛出一个 int void* . 首先,你应该经常使用 uintptr_t 如果你有这样的东西。使用 int 是一种虐待。

    那么,如果你的 尤因普特里特 不是来自有效地址。它只保证反过来。不要这样做。

    编辑: 这是C99标准的相关部分。正如你看到的,所有的警报都会响…

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

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

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

        4
  •  1
  •   JaredPar    16 年前

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

        5
  •  1
  •   Edward Strange    16 年前

    它的实现定义与上一个问题的定义相同,原因也相同。它不太可能导致错误行为,但它仍然是实现定义的。

        6
  •  1
  •   Mark B    16 年前

    不需要。在某些情况下,它似乎适用于特定的编译器设置,两年后,您将花费数周时间调试某些更改,而转换将不再按预期工作。

    如果您只是以一种不需要这种行为的方式设计您的代码(最佳情况完全避免使用这种转换,最坏情况下使用 char[] )以后你就不用担心隐藏的错误了。

        7
  •  0
  •   Oliver Charlesworth    16 年前

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

        8
  •  0
  •   R.. GitHub STOP HELPING ICE    16 年前

    如果整数的范围相当小,则可以执行如下操作:

    static const char dummy[MAXVAL];
    

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