我对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];
那么,我们知道,内存中b的布局如下:
b[0][0] b[0][1] ... ... b[m-1][n-1]
并且,内存中的布局如下:
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]
所以,我的问题是:由于[0..m-1] [0..n-1]不连续地存储在内存中,为什么我们可以使用下标运算符[]?换句话说,为什么a [i] [j]可以得到正确的元素,就像b [i] [j]那样?
解决方法
编译器单独处理表达式的每个部分. a [i] [j]和b [i] [j]之间的主要区别在于,由于a是指向int的指针,因此a [i]的地址计算会计算多个指针,但是,因为b是一个int数组的数组,b [i]的地址计算计算了许多数组. C使用表达式的每个部分的类型来确定如何评估它.
解释[i] [j]的步骤是:
> a是指向int的指针.
> a [i]被定义为*(a i).
>总和我是i元素超出分数的地方.由于指向int的指针,我们计算指向int的指针以确定新地址.
>由于sum是指向int的指针,因此将*应用于它会产生指向int的指针.
> a [i] [j]定义为*(a [i] j).我们已经评估了a [i]部分.
>总和a [i] j是超出a [i]指向的j个元素.由于a [i]指向int对象,我们计算j int对象以确定新地址.
>由于此和是一个指向int的指针,因此将*应用于它会产生一个int.
解释b [i] [j]的步骤是:
> b是n个int的m个数组的数组.>由于b是一个数组,它被转换为指向其第一个元素的指针,即一个n int数组.> b [i]被定义为*(b i).>总和b i是超出b点数的元素.由于b已被转换为指向n int数组的指针,因此我们计算n int的数组以确定新地址.>由于sum是指向n int数组的指针,因此将*应用于它会产生一个n int数组.>由于此表达式是另一个数组,因此它将转换为指向其第一个元素的指针,即int.> b [i] [j]定义为*(b [i] j).我们已经评估了b [i]部分.>和b [i] j是超出b [i]指向的j个元素.由于它指向int,我们计算j int以确定新地址.>由于此和是一个指向int的指针,因此将*应用于它会产生一个int.