结论:数组名是一个指针常量,其只能指向数组的首个元素所在地址。当数组作为函数参数时,会转化(有的也称退化)为一个指针,可以进行一些指针的操作,比如a++来读取下一个元素,但是其转化为的指针也还是指向这个数组的。
数组名不作为函数参数时,虽然是一个指针常量,但是不能完全作为一个指针来使用。数组作为函数参数时,就是当做一个指针来使用了。
#include <stdio.h>
#include <string.h>
int main(void)
{
int a[3] = { 1, 2, 3 };
printf("%d\n", *a);//结果为1。
此时数组名看起来又像是一个指针,但是却不能对这个指针进行++操作。
此时可能产生疑问,好像数组名在不作为函数参数的时候也能当作指针使用?那么为什么说数组名作为函数参数的时候才退化为指针呢。
实际上,数组名是这样使用的:数组名是一个指针,但是一个指针常量,其是一个指针常量的本质和其是否作为函数参数没有关系,数组名所表示的这个指针常量,是与对应的数组绑定的,不能再指向其他数组,所以数组名不作为函数参数时,不能有a++这种操作。
当一个函数的形参是数组时,在函数体内可以对这个形参进行a++这种操作,因为函数参数是数组,就已经能知道a++的意思不是让a这个指针常量再指向其他地址,而是通过a++读取下一个元素,所以在以数组作为函数形参的函数体中,a++这种操作是可以的,而且此时sizeof(a),永远是4。
当数组作为函数形参时,不需要指明数组大小,因为不管数组中有几个元素,实参传入时,传入的永远都是首个元素的地址。
printf("%d\n", sizeof(a));//12,此时数组名就是表示这个数组。
a++;//这是错误的,数组名a是一个指针常量,是不能变的,这么看数组名不是指针。
return 0;
}
void function(int a[])
{
a++;//这样又是可以的,因为数组名作为参数的时候,又退化成了指针,可以进行自加操作。
}
总的来说,不管是否作为函数的参数,数组名都是一个指针常量,只不过其作为函数参数时,因为已经定义了函数的参数是数组类型的,此时数组名就会退化为一个指针,在函数体中就当作是一个指向这个数组的指针来进行操作了。
看一下这篇文章,作为参考。https://www.cnblogs.com/youxin/p/3235862.html
再看下面一段代码:
#include <stdio.h>
#include <string.h>
int main(void)
{
int a[3] = { 1, 2, 3 };
int* p = a;
printf("%d\n", p);
int* p1 = &a;
printf("%d\n", p1);
return 0;
}
两个输出结果相同,可以发现a即可以认为是数组第一个元素的地址,也可以认为就是一个数组变量的名称,C是一种很灵活的语言。