【问题标题】:Why it is not safe casting a pointer to a numeric type?为什么将指针转换为数字类型是不安全的?
【发布时间】:2018-02-18 10:21:52
【问题描述】:

考虑这段代码

T* pa = new T(13);
int address = reinterpret_cast<int>(pa);

其中 T 可以是任何内置类型。

1) 我不明白在这里重新解释演员有什么问题??

2) 这种强制转换会导致未定义行为的情况是什么?

3) pa 是否总是包含正确的内存地址十进制表示?

【问题讨论】:

  • 整数和指针的大小不需要相同
  • 如果1 &lt;&lt; (sizeof(T*) * CHAR_BIT) 大于INT_MAX,那么您的地址值可能不适合int
  • @NeilButterworth 好的,可以说地址足够大,可以包含该十六进制值,可以说它很长
  • 通常是sizeof(int) &lt; sizeof(T *),所以“address”的值将不能代表pa的值。只要您只打印address 以供娱乐就可以了,但是一旦您想将其用于有用的事情就不能。
  • 另外,[u]intptr_t 就是为此目的而存在的。

标签: c++ c++11 pointers casting


【解决方案1】:

T*int 的大小取决于您的编译器和架构。

如果sizeof(T*) &gt; sizeof(int),您将丢弃信息。虽然这在一种编译器上可能是正确的,而架构在另一种编译器上可能不是正确的。

您可以使用std::intptr_tstd::uintptr_t 代替int。这两个保证足够大以保存指针的值。

【讨论】:

    【解决方案2】:

    我不明白在这里重新解释演员有什么问题?

    因为标准不要求ints 和指针具有相同的大小,因此您可能会因强制转换而丢失信息。

    这种强制转换会导致未定义行为的情况有哪些?

    如果这是真的:

    1 << (sizeof(T*) * CHAR_BIT) > INT_MAX
    

    那么地址的值可能不会填写int,这会调用未定义的行为。

    pa 是否总是包含内存地址的正确十进制表示形式?

    如果你使用std::[u]intptr_t,那么可以,因为这些类型保证能够保存指针的值。

    【讨论】:

    • 次要 nitpick:您链接的是 C 引用,而不是 C++ 引用
    • 我的意思是this one(因为它包含的信息表明这种类型只是C++11以来标准的一部分,也是可选的)
    • 所以 std::[u]intptr_t 的大小总是大于或等于指针类型?
    • @gsamaras 没有这样的原因,这是最有用的答案
    • @NickA - 这取决于您想要的便携性。有些系统没有int64_t like this one
    【解决方案3】:

    正如其他答案所指出的,整数的大小和指针的大小不必相同。例如,在许多 64 位 Intel 机器上,指针是 64 位,而整数只有 32。

    不过,还有其他原因可以防止这种情况发生。例如,一些较旧的处理器架构具有包含trap representations 的整数表示,如果使用会导致未定义的行为。这意味着原则上指针可以适应整数的大小,但是将指针转换为整数可能会导致陷阱表示,从而导致进一步的数字计算失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2012-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多