我假设嵌套的 std::array 不能假设内存是严格连续的:例如参见: 嵌套的 std::array 中的数据保证是连续的吗? 以及其他相关问题。 每个子数组的末尾可能有一些填充。 我找不到有关普通数组的等效信息。 是否能保证普通数组中的所有数据在内存中都是连续的? 例如:
uint8_t A[3][7];
可以肯定地说 A[1]-A[0] 是 7 吗?
附属问题:
sizeof
运算符在多维数组及其子数组之一上的行为应该是什么?
NB ISO/IEC JTC1 SC22 WG21 N4860 §9.3.3.4-9 规定:
[注:当多个“array of”规范相邻时,会创建多维数组类型;只有 指定数组边界的第一个常量表达式可以被省略。 [例子: int x3d[3][5][7]; 声明一个包含三个元素的数组,每个元素又是一个包含五个元素的数组,每个元素又是一个包含 七个整数。整个数组可以看作是一个三维整数数组,秩为 3 × 5 × 7。 任何表达式 x3d、x3d[i]、x3d[i][j]、x3d[i][j][k] 都可以合理地出现在表达式中。这 表达式 x3d[i] 等价于 *(x3d + i);在该表达式中,x3d 受数组到指针的约束 转换(7.3.2)并首先转换为指向二维数组的指针,该数组的秩为 5 × 7,该数组指向 x3d 的第一个元素。然后添加 i,这在典型的实现中涉及将 i 乘以 指针指向的对象的长度,即sizeof(int)×5 × 7。相加的结果 间接是一个左值,表示 x3d 的第 i 个数组元素(由五个数组组成的数组,每个数组有七个整数)。 如果还有另一个下标,则再次应用相同的参数,因此 x3d[i][j] 是表示第 j 个下标的左值 x3d 的第 i 个数组元素(七个整数的数组)的数组元素,并且 x3d[i][j][k] 是左值 表示x3d的第i个数组元素的第j个数组元素的第k个数组元素(整数)。 -结尾 示例]声明中的第一个下标有助于确定数组消耗的存储量 但在下标计算中不发挥其他作用。 ——尾注]
如果我理解正确,数据应该是连续的,但是“关于典型实现”部分让我感到困扰。所以我还需要确认。 (在这种情况下,我无法理解为什么 std::array 没有相同的保证)。
sizeof A
将等于
3 * 7 * sizeof(uint8_t)
。
sizeof A[0]
将等于
7 * sizeof(uint8_t)
。也就是说,
sizeof
运算符对于任何数组都按预期工作。
A[1]-A[0]
,由于
A[1]
和
A[0]
都是数组(类型为
uint8_t[7]
),因此它们将衰减为指向其第一个元素的指针。所以这个表情真的是
&A[1][0] - &A[0][0]
。因为每个子数组都是
7
个元素,所以结果将是
7
。请注意,无论元素类型如何,结果都是
7
,因为结果以元素类型为单位,而不是字节。
[A]保证是连续的普通嵌套数组是的,他们是。数组中没有填充。基本类型是什么、普通整数类型、结构或类对象或其他任何类型都没关系。
A[1] - A[0]
= 7,但它看起来像
&
A[1][0] and &A[0][0]
,因为这会给出其实际地址位置。是
7
,因为您可以通过 NB ISO/IEC JTC1 SC22 WG21 N4860 §9.3.3.4-9 的链接进行验证。在 C++ 中,标准是将多维数组布置在内存中的连续块中。当它提到“典型实现”时,它使用该术语的原因是因为不同的数据类型具有不同的大小,因此这会改变它的大小和步幅,但它的行为仍然相同并且是连续的。
sizeof 运算符的行为也一致。当您将 sizeof 应用于多维数组时,它会给出整个数组占用的总大小,如果您将 sizeof 应用于其子数组之一,它将给出该子数组的大小。
对于你的例子来说,它是
3*7*sizeof(uint8_t)
代表您的主阵列,
7*sizeof(uint8_t)
代表您的子阵列。现在说说为什么这与
std::array
不同。
std::array
可以使用用户定义的自定义类型。这些类型可以具有自定义布局、尺寸和设置。因此
std::array
不可能保证其始终连续,因为它不知道将传入的类型。也就是说,如果您不使用像 uint8_t 这样的用户定义类型,它将按照我上面描述的方式运行。