关于 C 编程语言 (ANSI-C) 的一个简单问题:
C 中的多维数组是锯齿状的吗?
我的意思是-我们是在谈论“数组数组”(一个指向内存中其他地址的指针数组),还是只是“长一维数组”(按顺序存储在内存中)?
困扰我的是,我有点确定:
matrix[i][j]
相当于* ( * (matrix + i) + j)
关于 C 编程语言 (ANSI-C) 的一个简单问题:
C 中的多维数组是锯齿状的吗?
我的意思是-我们是在谈论“数组数组”(一个指向内存中其他地址的指针数组),还是只是“长一维数组”(按顺序存储在内存中)?
困扰我的是,我有点确定:
matrix[i][j]
相当于* ( * (matrix + i) + j)
C 中的多维数组是连续的。以下:
int m[4][5];
由 4 个int[5]
s 组成,在内存中彼此相邻。
指针数组:
int *m[4];
是锯齿状的。每个指针都可以指向不同长度的单独数组(的第一个元素)。
m[i][j]
相当于*(*(m+i)+j)
。请参阅C11 标准,第 6.5.2.1 节:
下标运算符 [] 的定义是 E1[E2] 等同于 (*((E1)+(E2)))
因此,m[i][j]
等价于(*(m+i))[j]
,即等价于*(*(m+i)+j)
。
存在这种等价性是因为在大多数情况下,数组类型的表达式会衰减为指向其第一个元素的指针(C11 标准,6.3.2.1)。m[i][j]
解释如下:
m
是一个数组数组,所以它衰减到指向m[0]
第一个子数组的指针。m+i
是指向 的i
第 th 个子数组的指针m
。m[i]
等价于*(m+i)
,取消引用指向 的i
第 th 个子数组的指针m
。由于这是一个数组类型的表达式,它衰减为指向 的指针m[i][0]
。m[i][j]
等价于*(*(m+i)+j)
,取消引用指向 的第th 子数组的第j
th 元素的指针。i
m
请注意,指向数组的指针不同于指向其第一个元素的指针。m+i
是指向数组的指针;它不是数组类型的表达式,并且无论是指向指针的指针还是指向任何其他类型的指针,它都不会衰减。
一个连续的内存区域:
int arr[N][M];
一个非连续的内存区域:
int** arr = malloc(N*sizeof(int*));
for (int i=0; i<N; i++)
arr[i] = malloc(M*sizeof(int));
在这两种情况下,您都可以将arr
其用作二维数组(例如arr[1][2] = 3
)。但是您可以安全地应用更大的复制操作,例如memset(arr,0,N*M*sizeof(int))
,仅在第一种情况下。
这将取决于。
C中的多维数组是按顺序排列的。
如果你想使用指针,你可以创建锯齿状数组。
如果你声明一个多维数组,你会得到“长一维数组”(它是按顺序存储在内存中的)。
如果你声明一个指向指针的指针(指向指针......),你会得到数组的数组。
这种差异对于初学者 C 程序员来说是一个很困惑的根源。
一个或多个数组,例如int matrix[A][B]
不是锯齿状的,因为 的每个元素matrix
都是一个array of B int
.
您想知道*(*(matrix+i)+j)
is 的结果并将其与 的结果进行比较matrix[i][j]
。
既然 的类型matrix
是array of A array of B int
,那么表达式matrix+i
就是一个指向i
tharray of B int
的指针,matrix
它的类型是int (*)[B]
。取消引用此表达式会导致array of B int
. 该表达式*(matrix+i)+j)
产生一个指向该数组的j
th的指针。int
取消引用该表达式会导致int
. 这相当于表达式的matrix[i][j]
作用。
一个指针数组,例如int *matrix[A]
,可能是锯齿状的,因为 的每个元素matrix
可能指向不同大小的分配。
你是对的,那matrix[i][j]
等价于*(*(matrix + i) + j)
,因为arr[i]
等价于*(arr + i)
。但是,请记住,如果arr
声明为
int arr[64];
那么任何对的引用arr
都可以隐式转换为&arr[0]
,即指向第一个元素的指针。数组数组也会发生同样的事情:
int matrix[8][8];
这里matrix
有 type ,当你添加一个整数时int[8][8]
会自动转换为,如. 然后有 type ,当您添加时再次转换为 type ,因此有type ,因此具有预期的 type 。int (*)[8]
matrix + i
*(matrix + i)
int[8]
int *
j
*(matrix + i) + j
int *
*(*(matrix + i) + j)
int
所以重点是,数组不是指针,只是它们可以隐式转换为指向其第一个元素的指针。
因此,如果您像上面 ( ) 那样分配数组的数组int matrix[8][8];
,那么所有元素在内存中都是连续的。