int a[A][B];
int* p = a[i]; //i<A-1
然后下面句子的实际操作是什么?
p++;
p+=B;
答案 0 :(得分:13)
p++
- &gt;转到矩阵中的下一列
p+=B
- &gt;转到矩阵中的下一行(在同一列)。
答案 1 :(得分:4)
对于多维数组,必须记住从左到右应用维度,这使得可视化更容易一些。例如:
int p[A][B][C];
这将构建为:
[][]--[][][][]--[][]_ _ _[][]--[][] [][]--[][][][]--[][]_ _ _[][]--[][]
|---A----||---A----| |---A----|---|---A----||---A----| |---A----|
|---------------A*B---------------| |---------------A*B---------------|
|---------------------------------A*B*C---------------------------------|
所以,如果你有p [i] [j] [k],我实际上(p + i + Bj + BCk)
答案 2 :(得分:0)
初始化后,a存储A B ints,p指向B 第i个(基于0)。 后面的操作使它指向B *(i + 1)+ 1'。
答案 3 :(得分:0)
p = a[A-1]
与
相同p = &a[A-1][0]
所以
p++
结果
p == &a[A-1][1]
然后做
p+=B
将导致
p == &a[A-1][1+B] == &a[A][1] // outside allocated memory
答案 4 :(得分:0)
只是为了进一步加强对话(虽然我实际上无法直接回复cbailey的帖子而没有足够的代表......)
在堆栈上和堆上声明多维数组之间存在很大差异。
由于abelenky可能会进入,在堆栈上声明一个多维数组将始终导致连续的内存。我相信C标准实际上在某个地方说明了这一点,但即使它没有,地球上的每个编译器都会确保它是连续的。 这意味着在一天结束时,您可能也在使用单维数组,因为编译器无论如何都会转换为该数组。
就使用多维数组时的安全性而言,无论它们是在堆还是堆栈上分配,您都不希望以原始海报的方式迭代它们。
答案 5 :(得分:0)
这是一个元答案,很像Justicle和原始海报一样。
数组退化为指针,但它们不是同一个东西。只是因为a [3] [7] [1]的语法是相同的,如果a是指向指针指向int的指针而不是数组的数组 - -int并不意味着实际操作是相同的。
您可以创建一个任何类型的数组(定义良好的大小)。数组解除引用语法和指针语法是相同的,例如
a[i] == *(a+i) == i[a]
无论a是什么数组类型。
此主题中所有问题的答案都可以从中得出。
int a[3][2][17]; //a is an array of length 17.
int (*b)[3][2] = a[5]; //b is a pointer to the fifth element of a
int (*c)[3] = b[1]; //c points to the first element of b.
b += 1; // b now points to the sixth element of a. (c is unchanged)
c += sizeof(*b); // c points to the first element of b again.
请注意,如果不连续,这一切都不会起作用。如果它不起作用,那么数组的数组将与其他任何数组的工作方式不同。
答案 6 :(得分:-1)
如果你以记忆形式绘制a [A] [B]矩阵,也就是一个向量,并以p指向[i]的开头,然后应用这些操作,那么答案很简单。
答案 7 :(得分:-1)
要回答这个问题,首先需要了解多维数组如何在C中存储在内存中。
int a[A][B];
不考虑它在内存中的优化方式,第一个索引(A)实际上是指向第二个索引(B)的指针数组。 虽然内存可能是连续的,但无法保证 。
因此:
int a[A][B];
int **b;
上面的 a 和 b 之间的区别在于a的内存在进入范围时会被分配。
考虑到这一点,回答你的问题:
int* p = a[i]; // p = a[i][0]
p++; // p = a[i][1]
p+=B; // p = a[i][1+B]
使用现代编译器,可能已经分配了一个连续的内存块,相当于:
p = a[i+1][1];
但是不能保证内存是连续的,所以可能的情况是你现在有一个无效的指针。