int数据[3] [5];
是5元素数组的3元素数组。
为什么?从直觉上来说,如果int[3]
是3元素数组,而int[3][5]
应该是3元素数组的5元素数组。
答案 0 :(得分:5)
直觉应该来自于索引约定-因为它是一个数组数组,所以第一个索引选择元素这是一个数组,第二个索引选择的是选定数组的元素。那是:
data[2][4]
将选择数组编号2中的元素编号4(注意零基础)。
现在,正如您指出的那样,这样的数组的定义似乎有点违反直觉,但显然,这种方式只是为了与索引语法保持一致,否则会更加混乱。
答案 1 :(得分:1)
由于spiral rule之类的问题,C并非总是以直观的方式工作,尽管也许您在这里误用了它。
与任何一种语言一样,您需要接受其本身的语法,而不是您认为的语法,否则您将在语义层次上不断与该语言作斗争。
诸如cdecl之类的工具将其解释为:
将数据声明为int数组5的数组3
答案 2 :(得分:1)
这不符合C的声明符的概念。在声明程序中指定声明的指针性,数组性或功能性,而 type -ness由类型说明符 1 指定:< / p>
int *p; // *p is the declarator
double arr[N][M]; // arr[N][M] is the declarator
char *foo( int x ); // *foo( int x ) is the declarator
这允许您以紧凑的方式创建任意复杂的类型:
int *(*foo(void))[M][N];
foo
是一个不带参数的函数,它返回指向int
的N元素数组的M元素数组的指针。
因此,对象或函数的实际类型是通过类型说明符(和任何限定符)和声明符的 combination 来指定的。
不幸的是,“紧凑”只是说“让人眼花another乱”的另一种方式。这样的声明可能很难阅读和理解。这确实意味着诸如多维数组声明之类的内容读为“向后”:
+---------------------------------+
| |
v |
type arr -> array-of -> array-of -+
^
|
start here
但是,如果您逐步进行,这确实是有道理的。让我们从一些任意类型T
开始。我们将T
的数组声明为
T arr[N];
因此,arr
是T
的N个元素数组。现在我们将T
替换为数组类型R [M]
。这给了我们
R arr[N][M];
arr
仍然是某物的N元素数组,而某物是R [M]
,这就是为什么我们写arr[N][M]
而不是{{1 }}。