在第二个等级指针上使用下标运算符

xia*_*337 6 c arrays pointers

我对C中指针和数组的问题感到困惑.

让我们先看一段代码:

//case 1
int **a;
a = (int **)malloc(sizeof(int*)*m);
for(i = 0; i < m; i++)
    a[i] = (int *)malloc(sizeof(int)*n);

//case 2
int b[m][n];
Run Code Online (Sandbox Code Playgroud)

然后,我们知道,b内存中的布局如下:

b[0][0] b[0][1] ... ... b[m-1][n-1]
Run Code Online (Sandbox Code Playgroud)

并且,内存中的布局如下:

a
 \
 _\|
 a[0]  a[1] ... a[m-1]
  |    |
  |    |
  |   \|/
  |   a[1][0] a[1][a] ... a[1][n-1]
 \|/
a[0][1] a[0][2] ... a[0][n-1]
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:由于a[0..m-1][0..n-1]存储在内存中不连续地,为什么我们可以使用下标操作[]a?换句话说,为什么a[i][j]可以得到正确的元素,就像b[i][j]这样做?

Eri*_*hil 2

编译器单独处理表达式的每个部分。a[i][j]和之间的主要区别b[i][j]在于,由于a是指向 的指针int,因此 的地址计算会a[i]计算指针的数量,但是,由于b是 的数组的数组int,因此 的地址计算会b[i]计算数组的数量。C 使用表达式每个部分的类型来确定如何计算它。

口译的步骤a[i][j]是:

  • a是一个指向 的指针的指针int
  • a[i]被定义为*(a + i).
  • 总和a+ii超出 wherea点的元素。由于a指向 的指针int,我们对i的指针进行计数int以确定新地址。
  • 由于 sum 是指向 an 的指针int,因此*对其应用会产生一个指向 an 的指针int
  • a[i][j]被定义为*(a[i] + j). 我们已经评估了该a[i]部分。
  • 总和a[i] + jj超出 wherea[i]点的元素。由于a[i]指向int对象,我们对j int对象进行计数以确定新地址。
  • 由于这个和是一个指向 an 的指针int,应用*它会产生一个int

口译的步骤b[i][j]是:

  • b是 的m数组的数组n int
  • 由于b是一个数组,因此它被转换为指向其第一个元素的指针,即 的数组n int
  • b[i]被定义为*(b + i).
  • 总和b + ii超出 whereb点的元素。由于b已转换为指向 数组的指针n int,我们对i数组进行计数n int以确定新地址。
  • 由于总和是指向 数组的指针n int,因此*对其应用会产生一个 数组n int
  • 由于该表达式是另一个数组,因此它被转换为指向其第一个元素的指针,即int.
  • b[i][j]被定义为*(b[i] + j). 我们已经评估了该b[i]部分。
  • 总和b[i] + jj超出 whereb[i]点的元素。由于它指向int,我们通过计数j int来确定新地址。
  • 由于这个和是一个指向 an 的指针int,应用*它会产生一个int