当二维数组和多维数组作为C语言中的函数参数

可能重复:
如何在C ++中使用数组?

一维数组作为函数参数:

#include  #include  int func(int a[], int n) { int i; for(i = 0; i < n; i++) printf("%d ", a[i][j]); } int main(void) { int a[2] = {1,2}; func(a, 2); } 

它编译并正确运行。

但是当二维数组作为函数参数时:

 #include  #include  int func(int a[][], int n) { int i, j; for(i = 0; i < n; i++) for(j = 0 ; j < n; j++) printf("%d ", a[i][j]); printf("\n"); } int main(void) { int a[2][2] = {{1,2}, {3,4}}; func(a, 2); } 

它无法正确编译。 我必须修改这样的代码:

 #include  #include  int func(int a[][2], int n) { int i, j; for(i = 0; i < n; i++) for(j = 0 ; j < n; j++) printf("%d ", a[i][j]); printf("\n"); } int main(void) { int a[2][2] = {{1,2}, {3,4}}; func(a, 2); } 

我不知道为什么? 任何人都可以解释它是如何工作的? 非常感谢。

c中的数组(包括一维和多维)驻留在连续的内存块中。 这意味着当你定义char a[3] ,数组就像这样布局在内存中(原谅我可怕的ascii艺术技巧):

 | a[0] | a[1] | a[2] | 

对于二维数组char a[2][3] ,布局如下:

 | a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] | ^ +--- first row ends here 

因此,当您索引到二维数组a[i][j] ,编译器会生成与此等效的代码:

 *(a + i*3 + j) 

其中可以读作“跳过i行并在该行中获取单元格j”。 要实现此目的,编译器必须知道行的长度(这是第二个维度)。 这意味着第二个维度是类型定义的一部分!

因此,当您想要将2d数组传递给函数时,必须为类型定义指定所需的维度。

最近(例如C2011 ,也许是C99 ) C标准启用了可变长度数组,因此以下function确实有效

 int sum (int n, int t[n][n]) { int s = 0; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) s += t[i][j]; return s; } 

使用gcc-4.7 -std=gnu99 -Wall -O -c ex.c编译时没有警告,生成的汇编程序就是你所期望的

至于为什么int t[][]不起作用,这是因为整个t每个元素都是int []类型,它具有不确定的大小。

这是一个非常好的解释: http : //www.eskimo.com/~scs/cclass/int/sx9a.html

如果没有数组的第二个维度,编译器就不知道如何索引它。 这是因为编译器使用指针进行一些算术运算,找出在内存中找到值的位置。

C中的数组非常“弱”,通常仅在指向第一个元素的指针时在运行时表示。 当你声明像int a[][]这样的东西时,不可能知道如何计算每个元素的地址,因为类型声明没有说明。 这就是为什么它不会编译,因为类型无效。

如果你可以使用int a[][] ,然后调用它传递int big[8][8]int small[2][2] ,那么函数内部的代码就无法神奇地“适应”这些不同arrays的正确地址计算。 这就是为什么它不起作用的原因。

您可以编写像int *matrix, size_t width这样的通用函数int *matrix, size_t width并手动进行地址计算,即元素“ matrix[i][j] ”在matrix[i * width + j]进行行主要排序 。