写一个函数,打印数组内的内容,代码为:
#include<stdio.h>
void show_arr(int arr[], int num)
{
int i = 0;
for (i = 0; i < num; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,2,3,4,5,6 };
int num = sizeof(arr) / sizeof(arr[0]);
show_arr(arr, num);
return 0;
}
运行效果为:
在此代码中,我们使用数组的形式来接受数组,那么这两个数组是否相同???
我们可以通过测试数组的大小(sizeof 函数),来判定其是否相同,程序运行效果如下:
从上述运行结果可知,两个数组的大小并不一样。通过调试监视,我们可以下图效果:
我们可以看出 arr 的类型被降维成 int*
那么如果在此处我们使用指针来接受数组,是否可以??? 代码如下:
#include<stdio.h>
void show_arr(int *arr, int num)
{
printf("%d\n", sizeof(arr));
int i = 0;
for (i = 0; i < num; i++)
{
printf("%d ", *(arr+i));
}
printf("\n");
}
int main()
{
int arr[] = { 1,2,3,4,5,6 };
int num = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sizeof(arr));
show_arr(arr, num);
return 0;
}
程序运行成功后,效果为:
由此,我们可以得出以下结论:
数组传参,需要降维成指针。
1.为什么需要降维???
如果不降维的话,就会发生数组拷贝(全拷贝),会导致函数调用的效率降低,所以需要降维成指针。
2.在函数调用时是否形成了临时拷贝???
我们可以通过数组首元素地址进行判断,若两者首元素地址相同,则说明没有形成临时拷贝,若两者首元素地址不相同,则说明形成了临时拷贝。
&arr[0] 与 &arr 的区别:
&arr[0] --- 取出的是首元素的地址,即数组内容第一个元素的地址
&arr --- 取出的数组的地址,即整个数组的地址
测试代码为:
#include<stdio.h>
void show_arr(int arr[], int num)
{
printf("%p\n",&arr);
}
int main()
{
int arr[] = { 1,2,3,4,5,6 };
int num = sizeof(arr) / sizeof(arr[0]);
printf("%p\n", &arr);
show_arr(arr, num);
return 0;
}
运行效果为:
指针变量也是变量,在进行函数调用时,也要发生拷贝(拷贝指针)--- 调用函数形成临时拷贝。
•在C语言中,任何函数调用,只要有形参实例化,必定形成临时拷贝。
3.降维成什么指针???
我们的示例举的都是一维数组的例子,在此处,我们举一个二维数组的列子:
由上述可知:
所有的数组传参都会降维成指针,降维成为指向其(传入的数组)内部元素的指针。
C语言是面向过程语言,在进行数组传参的时候,为了效率,将其降维成指针。
4.C语言为什么要把指针和数组的访问设计成通用的???
如果指针和数组访问方式不统一,程序员需要不断地在不同的代码片段处,进行习惯的切换,本质上就会增加代码的出错率。
为了让程序员统一使用数组,并且减少出错的概率,数组和指针的访问方式设计成通用的。即,整个降维的过程,对用户是透明的。