今天我们接着前两天的内容继续讲解
一、数组名的理解
1、&arr[0]与arr
有时候我们需要获取数组首元素,有两种方法可以获取。
使用这两种方法都可以获得数组首元素&arr[0],arr。
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10};printf("%d ", &arr[0]);printf("%d ", arr);return 0;
}
输出:
输出的内容就是首元素的地址。
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10};printf("%d\n", sizeof(arr));return 0;
}
输出:
对于这一题同学们就疑惑了,不是arr可以获得数组首元素地址吗,怎么在这段代码中就不是了。
有两种情况:
1、sizeof(数组名)单独存在sizeof中的数组名是用来求数组大小的。
2、&数组名,这是用来获取整个数组地址的。
2、&arr与arr
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10};printf("%d\n", &arr);printf("%d\n", arr);return 0;
}
输出:
我们发现获取整个数组地址跟获取数组首元素地址打印出来的地址是一样的,那到底他们有什么不一样呢,如果我们把这两个都+1会是什么效果。
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10};printf("%d\n", &arr);printf("%d\n", &arr + 1);printf("%d\n", arr);printf("%d\n", arr+1);printf("%d\n", &arr[0]);printf("%d\n", &arr[0]+1);return 0;
}
输出:
数组之间元素的间距是一个int类型,一个int类型等于4个字节。
我们看见,&arr+ 1,跳过了整个数组,就是40个字节。
而arr+1跳过了一个int类型,那就是3个字节。
二、使⽤指针访问数组
void add(int* p, int sz)
{for (int i = 0; i < sz; i++){printf("%d ", *(p + i));}
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);add(arr, sz);return 0;
}
输出:
在以前的时候,我们在接收函数传过去实参的时候,都是使用形参来接收。
void add(int* p, int sz),大家可以看见,我们使用指针同样是可以接收传过去的数组的,p指针接收的是arr数组中首元素的地址。通过循环语句从首元素打印,一直打印完数组全部。
printf("%d ", *(p + i));这一行代码,*(p+i)等于p[i],这两种写法都可以,在编译器编译的时候,是通过指针实现的。
*(p + i),
*(p+0)=1
*(p+1)=2
*(p+2)=3
……
*(p+9)=10
那么同样通过指针输入数值到数组里吗?
当然也是可以的:
void add(int* p, int sz)
{for (int i = 0; i < sz; i++){printf("%d ", *(p + i));}
}int main()
{int arr[10] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;for (int i = 0; i < sz; i++){scanf("%d", p+i); //arr+i也可以}add(arr, sz);return 0;
}
三、一维数组的传参本质
void add(int arr[ ])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2=%d\n", sz2);
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);add(arr);printf("sz1=%d\n", sz1);return 0;
}
输出:
sz1与sz2为什么得到的结果不一样呢。
因为在函数add中,传过去的是arr[ ] 这并不是整个数组的地址,而不是数组首元素的地址。
void add(int* arr) //int* arr = int arr[0]
{int sz3 = sizeof(arr) / sizeof(arr[0]);printf("sz3=%d\n", sz3);
}
我们也可以通过指针传参把首元素给传过去。
总结:一维数组传参可以使用指针来传,也可以通过数组形式来传参
四、⼆级指针
二级指针指向的是一级指针。
int main()
{int a = 10;int* pa = &a;int** paa = &pa;return 0;
}
**paa = 30;
printf("%d\n", a);//输出30;
**paa可以直接修改a变量的,因为**paa中存放的是*pa,而*p存放的是a的地址。
五、指针数组
数组指针是存放指针的数组
六、指针数组模拟⼆维数组
int main()
{
int arr1[5] = {1,2,3,4,5};
int arr2[5] = {2,3,4,5,6};
int arr3[5] = {3,4,5,6,7};
int* arr[3] = { arr1,arr2,arr3 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
可以看见,我们通过使用一维数组实现了二维数组,代码中最重要的一点就是指针数组,指针数组把一维数组中首元素地址给放到了一个数组中,我们通过循环遍历就可以打印出每个一维数组中的值。