前言
我们都知道C语言中的数组参数会退化为指针,那有没有想过为什么呢?由于C语言当初开发是为UNIX操作系统的,对于操作系统来说效率是非常重要的,当参数传递的时候如果拷贝整个数组执行效率将大大下降而且参数位于栈上,太大的数组拷贝将导致栈溢出,所以会将数组名看做常量指针传数组首元素地址,其实二维数组参数同样存在退化的问题,二维数组可以看做是一维数组且每个元素是一维数组,如下
void f(int a[5])<->void f(int a[])<->void f(int *a)
void g(int a[3][3])<->void g(int a[][3])<->void g(int(*a)[3])
也就是说我们在向一个函数传递数组参数的时候,必须提供第一维以外的所有维长度,因为第一维以外的维度信息用于指针运算,N维数组的本质一维数组,元素是N-1维的数组,对于多维数组的函数参数只有第一维是可变的
深入分析
#include <stdio.h>
#include <stdlib.h>
void test(int a[][3],int row)
{
int col = sizeof(*a)/sizeof(int);
int i = 0;
int j = 0;
printf("sizeof(a) = %d\n",sizeof(a));
printf("sizeof(*a) = %d\n",sizeof(*a));
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
{
printf("%d\n",a[i][j]);
}
}
printf("\n");
}
void test1(int b[][3][4],int n)
{
int i = 0;
int j = 0;
int k = 0;
printf("sizeof(b) = %d\n",sizeof(b));
printf("sizeof(*b)= %d\n",sizeof(*b));
for(i=0;i<n;i++)
{
for(j=0;j<3;j++)
{
for(k=0;k<4;k++)
{
printf("%d\n",b[i][j][k]);
}
}
}
}
int main(void)
{
int a[2][3] = {{1,2,3},{4,5,6}};
int aa[2][3][4] = {0};
test(a,2);
test1(aa,2);
return 0;
}
结果:
sice@sice:~$ ./test1
sizeof(a) = 4
sizeof(*a) = 12
1
2
3
4
5
6
sizeof(b) = 4
sizeof(*b)= 48
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
可以看出从本质上来说C语言只有一维数组,sizeof(a)和sizeof(b)为4可以看出a,b是退化成指针,sizeof(*a) = 12是其二维数组的第一行数组的长度,sizeof(*b)=48是其三维数组的第一行的长度也就是二维数组的长度