【问题标题】:How to specify a pointer which points to unaligned int?如何指定指向未对齐int的指针?
【发布时间】:2015-11-10 02:44:58
【问题描述】:
struct Intx4 {
  int data[4];
};

Intx4 loadIntx4(void const *p) {
  auto up alignas(1) = (int const *)p; // Does this line correct? (compiled ok in clang)
  Intx4 r;
  for (int i = 0; i < 4; i++) r.data[i] = up[i];
  return r;
}

我也尝试了以下方法,它们都无法在clang中编译:

int const *up alignas(1) = (int const *)p;
auto up = (int const alignas(1) *)p;

【问题讨论】:

  • 为什么不直接发送 Intx4 参考?这比 C++ 更像 C,除了 alignas
  • 我只是想知道如何表达从未对齐的内存地址读取 int。
  • 当心,从未对齐的地址读取 int 会在某些架构 (ARM) 上引发异常,并且在所有 C++ 版本中都是明确未定义的行为。
  • @SergeBallesta:由于 C++ 仅开始指定从 C++11 开始的内存模型,我会质疑您关于未对齐内存地址导致未定义行为的说法。在 C++11 中甚至不是这样。
  • @IInspectable,内存模型描述了内存操作在存在多个线程的情况下如何表现,但这与这里无关。对齐要求一直是 C++ 的一部分。

标签: c++ c++11 alignas


【解决方案1】:

读取未对齐的整数:

int i;
void* ptr_to_unaligned;
...
memcpy (&i, ptr_to_unaligned, sizeof(i));

C++ 中没有未对齐的整数类型,因此您必须使用void*

【讨论】:

    【解决方案2】:

    根据 C++11 草案 (n4296),尝试将指向 void 的指针转换为具有对齐要求的类型会调用未定义的行为

    从 5.2.9 静态转换第 13 节开始:“指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 为 一个对象类型,并且 cv2 与 cv1 具有相同的 cv 限定或大于 cv1 的 cv 限定...如果原始指针值表示 一个字节在内存中的地址A并且A满足T的对齐要求,则得到的指针 value 表示与原始指针值相同的地址,即 A。任何其他此类指针转换的结果都未指定(强调我的)

    我知道您正在使用显式转换(或 C 样式转换),但 5.4 显式转换说:由 const_cast (5.2.11)、static_cast (5.2.9)、static_cast 执行的转换后接 const_cast、reinterpret_cast (5.2.10) 或 reinterpret_cast 后接 const_cast, 可以使用显式类型转换的强制转换表示法来执行。相同的语义限制和行为适用...

    因此,在您的情况下,显式转换与 static_cast&lt;int const *&gt;(p) 相同。

    当您尝试访问未对齐的 int 指针时,某些架构(尤其是 ARM 架构)会陷入陷阱,如 that other SO answer 中所述

    【讨论】:

    • 这不是直接的答案,最初是作为评论发布的,但我想添加不适合评论的参考。
    • 另外 [basic.life] 表示对象的生命周期在获得适当大小和对齐的存储时开始(如果相关,则其构造函数运行)。如果您没有适当对齐的存储,则无法在该地址创建对象,因此通过 [basic.lval] 从该地址读取值是未定义的行为,因为该地址没有该动态类型的对象。
    【解决方案3】:

    要以非对齐方式使用整数,请将单词 __packed 放在整数指针声明的前面:

    __packed int *pi; // pointer to unaligned int
    

    Unaligned pointers in C and C++ code

    【讨论】:

      猜你喜欢
      • 2017-01-11
      • 2013-07-11
      • 1970-01-01
      • 2015-09-10
      • 2015-07-13
      • 2018-06-08
      • 2017-09-03
      • 2021-02-07
      • 2021-07-26
      相关资源
      最近更新 更多