不知道大家在学习的时候,有没有这样的困惑:数组的下标为什么从0开始?从1开始不是更容易理解吗?既然数组传参传递的是首元素的地址,为什么函数的形参我们仍然可以写成数组的形式?(这样形参和实参是不是就不对应了呢?)
1.为什么数组下标从零开始 ?
先说说我的理解:[ ]这个操作符实际相等价于指针加减和解引用两个步骤,而他的操作数的含义是:相对于起始位置的偏移量。我们都知道数组名代表首元素的地址,所以,第一个元素相对于首元素的偏移量当然为0喽,也即:数组的下标从0开始。
下面我们从代码的角度来理解一下吧:
#include <stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,0};
int i=0;
for(i=0;i<10;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
for(i=0;i<10;i++)
{
printf("%d ",*(arr+i));
}
return 0;
}
两个for 循环打印出来的结果完全相同,可见这里arr[i]等价于*(arr+i),i代表后面的元素相对于首元素的偏移量。
2.为什么数组的形参可以写成数组?
首先应该明确的是:数组传参时传递的是首元素的地址。那么,为什么数组的形参仍然可以写成数组的形式呢?
本质还是由于[ ]这个操作符,具体原因已在下面代码中注释
#include <stdio.h>
void Print(int* arr,int sz)//既然传参传的是首元素的地址,那么我拿一个相同类型的指针arr来接收
{
int i=0;
for(i=0;i<sz;i++)
{
printf("%d ",*(arr+i));//前面讨论过*(arr+i)等价于arr[i],所以,虽然数组传参传递的是首元素地址,在函数内部依然可以像访问数组元素一样使用[]操作符找到数组里每一个元素,就仿佛传递了整个数组过来,所以形参也可以写成 int arr[]的形式
}
}
int main()
{
int arr[]={1,2,3,4,5,6,7,8,9,0};
int sz=sizeof(arr)/sizeof(arr[0]);
Print(arr,sz);//自己定义一个函数,实现打印数组元素功能
return 0;
}
#include <stdio.h>
void Print(int(*arr)[3],int row,int col)//二维数组首元素是一维数组,因此,拿一个数组指针来接收
{
int i=0;
for(i=0;i<row;i++)
{
int j=0;
for(j=0;j<col;j++)
{
printf("%d ",*(*(arr+i)+j));//arr是一个指向第一行元素的数组指针时
//第i行j列的元素为:*(*(arr+i)+j)
//按照前面说的:*(*(arr+i)+j)=*(arr+i)[j]
//*(arr+i)[j]=arr[i][j]
//所以虽然传递的是指针,访问元素时和传递的是数组写法相同
}
printf("\n");
}
}
int main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
Print(arr,2,3);//定义一个函数,用于打印数组中的每一个元素
return 0;
}
3.数组的大小为什么需要单独传递?
理解了前面的内容就不难理解这个问题,因为数组作为参数传递时传递的是一个地址,形参实际拿一个地址来接收,但是并不知道数组的大小。
当然,至于数组传参为什么传递的是指针而不是整个数组,当然为了节省空间,指针变量存储的是地址,所占空间大小是一定的(32位4个字节,64位8个字节),而拷贝整个数组可能花费很大空间。