目录
一、一维数组名作为输入参数,数组名代表数组首元素首地址
int main()
{
char arr[] = {'a', 'b', 'c', 'd'};
printf("%d\n", arr);
return 0;
}
运行上面程序会有以下警告
由警告可知,arr作为输入参数时,其数据类型是char*,也就是指针。
再看下方的程序:
int main()
{
char arr[] = {'a', 'b', 'c', 'd'};
printf("%p\n", arr);//直接输入数组名作为函数输入参数
printf("%p\n", &arr[0]);//利用取地址符&,取出数组首元素地址
return 0;
}
由下方运行结果可知,C语言中数组名作为输入参数时,传递的是数组首元素的地址。
二、arr与&arr作为输入参数的区别
int main()
{
char arr[] = {'a', 'b', 'c', 'd'};
printf("%p\n", arr);
printf("%p\n", arr+1);
printf("%p\n", &arr);
printf("%p\n", &arr+1);
return 0;
}
运行结果:
根据上面的运行结果可知,arr和&arr作为printf函数输入参数时,打印出来都是首元素的地址(指针指向数组时,存储的都是数组首元素地址,但是其执行的地址空间确实不同的)。但是,我们还发现arr偏移一个单位,地址偏移1,而&arr偏移一个单位,地址却偏移了4。
这是因为,arr类型为char*,其指向1字节的空间,而&arr类型为char(*)[4],指向4字节空间(也就是数组指针)。而指针偏移一个单位的大小取决于其指向的字节大小。
当我们输入&arr作为参数时,其是指向整个数组的指针,虽然打印出来还是首元素地址,但是其代表的是,整个数组的开始地址。当我们输入&arr+1时,打印出来的地址是整个数组的开始地址加上一个单位的偏移量。
由上方程序可知,arr中储存了4个字符,运行程序,监视数组可知,数组arr的数据类型是char[4],代表其数据类型是4个char类型。
所以说,因为arr直接作为输入参数,代表的是首元素地址,其仅仅指向首元素,也就是char类型,所以其偏移一个单位是1个字节;而&arr作为输入参数时,代表的是整个数组,而整个数组的数据类型是char[4],所以其偏移一个单位是4个字节。
还要注意的一个情况:sizeof不是函数,其是关键字,sizeof arr 计算时,arr代表的是整个数组,sizeof arr 计算结果是整个数组的字节数。
总结来说,我们只需要记住&arr以及sizeof arr,arr代表整个数组,其余arr都表示首元素地址。
三、数组实参传递给数组形参,形参改变,实参也会改变
void test(char arr[])
{
arr[0] = '*';
}
int main()
{
char arr[] = {'a'};
test(arr);
printf("%c\n", arr[0]);
return 0;
}
运行结果为 *
这是因为在C语言中,数组的传递是通过指针来实现的。当你将一个数组作为实参传递给一个函数时,实际上传递的是数组的首地址,也就是数组的指针。
在函数内部,形参会接收到这个指针,它和实参指向同一个内存地址。因此,任何对形参所指向的内存的修改都会影响到实参所指向的内存,从而改变了原始数组的内容。
换句话说,数组的传递是按址传递的,而不是按值传递。这也是为什么在函数内部对数组的修改会反映到函数外部的原始数组上的原因。
如果你想在函数内部修改形参数组而不影响实参数组,可以在函数内部创建一个临时数组,并将实参数组的内容复制到临时数组中进行操作。这样可以保持实参数组的原始内容不变。