【问题标题】:Is accessing the middle of a multidimensional array via a pointer to its first element UB?是否通过指向其第一个元素 UB 的指针访问多维数组的中间?
【发布时间】:2019-04-30 18:12:26
【问题描述】:

考虑以下代码:

int data[2][2];
int* p(&data[0][0]);
p[3] = 0;

或等效:

int data[2][2];
int (&row0)[2] = data[0];
int* p = &row0[0];
p[3] = 0;

我不清楚这是否是未定义的行为。 p 是指向具有 2 个元素的数组 row0 的第一个元素的指针,因此 p[3] 访问数组的末尾,根据 7.6.6 [expr.add] 是 UB:

  • 将整数类型的表达式 J 与指针类型的表达式 P 相加或相减时,结果的类型为 P。
    • 如果 P 的计算结果为空指针值,而 J 的计算结果为 0,则结​​果为空指针值。
    • 否则,如果 P 指向带有 n 元素的数组对象 x 的元素 x[i],则表达式 P + J 和 J + P(其中 J 的值 j)指向(可能是假设的)元素 x[i+j] 如果 0 ≤ i + jn 并且表达式 P - J 指向(可能是假设的)元素 x[i−j] 如果 0 ≤ i − j ≤ @ 987654336@.
    • 否则,行为未定义。

我在标准中没有看到任何对多维数组进行特殊处理的东西,所以我只能得出结论,以上实际上是UB。

我说的对吗?

data 被声明为std::array<std::array<int, 2>, 2> 的情况如何?这种情况似乎更有可能是 UB,因为结构可能有填充。

【问题讨论】:

标签: c++ multidimensional-array


【解决方案1】:

是的,你是对的,没有什么可补充的。 C++类型系统中没有多维数组,只有数组(of arrays of arrays of arrays ad libitum)。

访问超出数组大小的元素是未定义的行为。

【讨论】:

  • 我觉得用多维数组这个词是公平的。 int[][] 是一个包含两个 rank 的数组。它是一种适当的数组类型,并且多维清楚地表明它具有多个范围。这也是cppreferencethe standard 使用的术语(至少在我在这里检查和链接的修订版中)。
  • @FrançoisAndrieux 我有理由将 C++ 中的 [][] 构造视为数组数组而不是多维数组(这个问题就是其中之一!)。即使在您的链接引用中,“多维”似乎或多或少是非正式的,正式类型如下:... type of the identifier of D is “array of N T...。多维数组在 C++ 类型系统中并不正式存在,我认为实现它有助于理解。
  • 你让它听起来像是一种观点,但语言规范定义了这个术语。 int[2][2]是“2个数组int的数组”,写成“当多个“数组”规格相邻时,创建一个多维数组类型;”。我不明白还有什么解释空间。
  • @FrançoisAndrieux 因为没有这种类型。您可以将其称为多维数组,但 C++ 中没有这种类型。正如我所引用的,标准本身正式将类型定义为 N T 的数组。就像我已经说过的那样,这个问题本身就是我将它们称为数组数组的一个很好的理由。
  • @SergeyA 如果您的意思是“多维数组”不是一种类型,我同意它不是 a 类型。但它当然可以用来描述或表征一个类型,你可以询问一个类型是否是一个多维数组。标准中列出了该问题的答案。因此,在讨论 c++ 时,它绝对是一个有效的术语,与您的回答相反,有 are 多维数组,因为存在可以回答“这种类型是多维数组吗?”这个问题的类型。 由语言定义为是。
猜你喜欢
  • 2019-12-28
  • 2012-12-20
  • 2021-10-08
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
相关资源
最近更新 更多