【问题标题】:Casting between primitive type pointers原始类型指针之间的转换
【发布时间】:2013-02-08 12:59:11
【问题描述】:

下面的定义是否明确:

char* charPtr = new char[42];
int* intPtr = (int*)charPtr;

charPtr++;
intPtr = (int*) charPtr;

intPtr 未正确对齐(至少在两种情况中的一种情况下)。放在那里是违法的吗? UB 在任何阶段都在使用它吗?怎么用,怎么不能?

【问题讨论】:

  • 如果您在此之后尝试使用intPtr,则会发生未对齐的访问(在相关处理器上)。所以绝对不能接受。虽然它可能适用于某些处理器 - 例如x86 会很高兴地读取未对齐的内存,但速度会慢一些。
  • 我认为你可以回退,但不能在施法后使用它:) 不过我必须检查一下。
  • “你能把它扔回去吗?”是什么意思
  • @JohnDibling 删除了该部分(发现需要回滚才能工作)。
  • C++ 中最好使用static_cast 而不是C 样式转换。

标签: c++ language-lawyer strict-aliasing


【解决方案1】:

通常,如果int 的对齐要求大于char 的对齐要求,则结果是未指定的(5.2.10p7),通常情况下。结果将是 int * 类型的有效值,因此它可以是例如打印为带有operator<< 的指针或转换为intptr_t

因为结果有一个未指定的值,除非由实现指定,否则间接它并对结果 int 左值执行左值到右值转换是未定义的行为(在未评估的上下文中除外)。转换回char * 不一定是往返。

但是,如果原始char * 本身是从int * 转换的结果,那么转换到int * 算作往返的后半部分;在这种情况下,演员表被定义。

特别是,在上述char *new[] 表达式的结果的情况下,我们保证(5.3.4p10)char * 指针与int 正确对齐,只要sizeof(int) <= 42。因为new[] 表达式从分配函数获得其存储空间,所以适用3.7.4.1p2; void * 指针可以转换 指向具有基本对齐要求的任何完整对象类型的指针,然后用于访问对象 [...] 这强烈暗示,连同对 5.3.4p10 的注释,@987654338 也是如此new[] 表达式返回的 @ 指针。在这种情况下,int * 是指向未初始化的int 对象的指针,因此对其间接执行左值到右值转换是未定义的(3.8p6),但分配给它的间接是完全定义的。 int 对象在分配的存储空间中 (3.7.4.1p2),因此将int * 转换回char * 将产生每1.8p6 的原始值。这不适用于递增的char * 指针,因为除非sizeof(int) == 1 它不是int 对象的地址。

【讨论】:

  • 原来的char*new char[42]的结​​果。
【解决方案2】:

首先,当然:指针保证在 第一种情况(根据 §5.3.4/10 和 §3.7.4.1/2),可能是正确的 在这两种情况下对齐。 (显然,如果sizeof(int) == 1,但是 即使不是这种情况,实现也不会 必须有对齐要求。)

为了明确一点:你的演员都是reinterpret_cast

除此之外,这是一个有趣的问题,因为就 我可以说,就这两个演员表而言,没有区别 标准有关。转换的结果是 未指定(根据 §5.2.10/7);你甚至没有保证 将其转换回char* 将导致 原值。 (例如,它显然不会在机器上 其中int* 小于char*。)

在实践中,当然:标准要求返回 new char[N] 的值对于任何值都充分对齐 这可能适合它,所以你保证能够做到:

intPtr = new (charPtr) int;

这与你的施法效果完全相同,因为 int 的默认构造函数是无操作的。 (并假设 sizeof(int) <= 42.) 所以很难想象一个实现 其中第一部分失败。您应该可以使用 intPtr 就像任何其他合法获得的 intPtr。和 将其转换回char* 的想法会以某种方式导致 与原始 char* 的值似乎不同 荒谬。

在第二部分,所有的赌注都被取消了:你绝对不能 取消引用指针(除非您的实现保证 否则),也很有可能将其转换回来 到char* 会产生不同的结果。 (想象一个词 寻址机器,例如,将char* 转换为 int* 向上取整。然后转换回来会导致 char* 比原来的 sizeof(int) 高。要么 总是导致转换未对齐指针的尝试 在一个空指针中。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-09
    • 2019-06-16
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 2011-02-01
    相关资源
    最近更新 更多