5

我偶尔会使用多维数组,并且很好奇标准对(C11 和/或 C++11)关于使用比为数组声明的“维度”更少的“维度”进行索引的行为。

鉴于:

int a[2][2][2] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};

标准是否说明了什么类型a[1]a[0][1]合法的,以及是否应该按预期正确索引子数组?

auto& b = a[1];

std::cout << b[1][1];
4

4 回答 4

5

m[1]只是类型int[2][2]。同样m[0][1]是刚刚int[2]。是的,作为子数组的索引按您认为的方式工作。

于 2013-08-01T13:52:37.550 回答
3

标准是否定义了a[i]where ais的类型T [M][N]

当然。该标准基本上定义了所有表达式的类型,如果没有,那就是缺陷报告。但我猜你对那种类型可能更感兴趣......

虽然标准可能没有明确提及您的情况,但规则已经说明并且很简单,给定type 元素的数组a,表达式是 type 的左值表达式。在变量声明中,类型为2 个元素的数组,类型为 2 个元素的数组,应用上面的规则意味着它是2 个元素的数组的左值,或者你必须在程序中键入它:添加额外维度不会影响机制。NTa[0]Tint a[2][2]ainta[0]int (&)[2]

于 2013-08-01T14:10:57.483 回答
2

我认为 C11 中的这个例子隐含地解释了它。

C11 6.5.2.1 数组下标

示例考虑由声明定义的数组对象int x[3][5];x是一个 3 × 5 的整数数组;更准确地说,x是一个由三个元素对象组成的数组,每个对象都是一个由五个整数组成的数组。x[i]在等价于的表达式中(*((x) + (i)))x首先将其转换为指向五个整数的初始数组的指针。然后i根据 的类型进行调整x,这在概念上需要乘以指针指向的对象的大小,即五个对象i的数组。int添加结果并应用间接以产生五个整数的数组。当在表达式中使用时x[i][j],该数组又被转换为指向第一个整数的指针,因此x[i][j]产生一个int.

类似的是在 C++11 8.3.4 数组中

示例:考虑

int x[3][5];

x是一个 3 × 5 的整数数组。当x出现在表达式中时,它被转换为指向(三个中的第一个)五元整数数组的指针。x[i]在等价于的表达式中*(x + i)x首先将其转换为所描述的指针;然后 x + i 转换为 的类型x,这涉及乘以i指针指向的对象的长度,即五个整数对象。将结果相加并应用间接以产生一个数组(由五个整数组成),然后将其转换为指向第一个整数的指针。如果有另一个下标,同样的论点再次适用;这次结果是一个整数。—结束示例] —结束说明]

于 2013-08-01T14:20:13.120 回答
1

要记住的关键点是,在 C 和 C++ 中,多维数组只是数组的数组(因此 3 维数组是数组数组的数组)。多维数组的所有语法和语义都遵循于此(当然也遵循该语言的其他规则)。

所以给定一个对象定义:

int m[2][2][2];

m是一个类型的对象int[2][2][2](两个数组的数组,每个数组由两个元素组成,每个元素由两个元素组成,每个元素是两个ints的数组)。

当您编写时,m[1][1][1]您已经在评估m和。m[1]m[1][1]

该表达式m是一个左值,引用类型为 的数组对象int[2][2][2]

m[1]中,数组表达式m被隐式转换为(“衰减”到)指向数组第一个元素的指针。这个指针的类型是int(*)[2][2],一个指向 的二元素数组的二元素数组的指针intm[1]根据定义等价于*(m+1); 前进+1一个m元素并取消引用结果指针值。som[1]指的是一个类型的对象int[2][2](一个由两个数组组成的数组,每个数组由两个int元素组成)。

(数组索引运算符[]被定义为对指针,而不是数组进行操作。在常见的情况下,例如arr[42],指针恰好是隐式数组到指针转换的结果。)

我们对 重复这个过程,给我们一个指向两个s (类型为)m[1][1]的数组的指针。intint(*)[2]

最后,m[1][1][1]获取评估结果m[1][1]并再次重复该过程,给我们一个指向类型对象的左值int。这就是多维数组的工作方式。

只是为了增加轻浮性,像这样的表达式foo[index1][index2][index3]可以直接使用指针以及数组。这意味着您可以使用指针和任意大小的分配来构造(几乎)像真正的多维数组一样工作的东西。这使您有可能拥有每行中具有不同数量元素的“参差不齐”的数组,甚至是缺少的行和元素。但是接下来由您来管理每一行甚至每个元素的分配和释放。

推荐阅读: comp.lang.c FAQ的第 6 节。

附注:在某些语言中,多维数组不是数组的数组。例如,在 Ada 中(数组索引使用括号而不是方括号),您可以拥有一个数组数组,索引为arr(i)(j),或者您可以拥有一个二维数组,索引为arr(i, j)。C 不同;C 没有对多维数组的直接内置支持,但它为您提供了自己构建它们的工具。

于 2013-08-01T15:25:57.897 回答