【C语言】 一维数组传参的本质
前言:
在C语言中,数组作为函数参数传递时,其本质是传递数组首元素的地址。这一特性使得数组在函数间的数据传递变得高效且灵活。本文将深入探讨一维数组传参的本质,并通过具体代码示例进行说明。
数组名与数组首元素地址的关系
在C语言中,数组名通常代表数组首元素的地址。例如,对于一个整型数组arr
,arr
等价于&arr[0]
。这种关系在大多数情况下成立,但在使用sizeof
或取地址运算符&
时,数组名表示整个数组,而不是首元素的地址。
int arr[10];
printf("%p\n", arr); // 输出数组首元素的地址
printf("%p\n", &arr[0]); // 输出数组首元素的地址
printf("%zu\n", sizeof(arr)); // 输出整个数组的大小
一维数组传参的本质
当一维数组作为函数参数传递时,实际上传递的是数组首元素的地址。因此,在函数内部,形参可以定义为指针类型或数组类型。这两种形式在编译时会被视为相同的指针类型。
典型代码
使用数组形式作为形参
#include <stdio.h>
void print(int arr[]) //函数调用
{
int i;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(arr); // 将数组传递给print函数
return 0;
}
使用指针形式作为形参
#include <stdio.h>
void print(int *p) //调用指针
{
int i;
for (i = 0; i < 10; i++) {
printf("%d ", *(p + i));
}
printf("\n");
}
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(arr); // 将数组传递给print函数
return 0;
}
在这两个示例中,print
函数都可以正确地访问并输出数组中的元素。这是因为无论形参定义为数组形式还是指针形式,编译器都会将其视为指向数组首元素的指针。
形参数组大小的指定
在函数声明中,可以指定形参数组的大小,但这并不会影响实际传递的参数。例如:
void print(int arr[10]) {
int i;
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
上述代码中的arr[10]
实际上等价于int *arr
。指定数组大小只是为了提高代码的可读性,并不会改变传递的是指针这一事实。
计算数组元素个数
在函数内部,无法直接通过sizeof
计算数组的元素个数,因为sizeof(arr)
计算的是指针的大小,而不是整个数组的大小。因此,通常需要将数组的大小作为额外的参数传递给函数。
#include <stdio.h>
void print(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
print(arr, 10); // 将数组和数组大小传递给print函数
return 0;
}
因为数组中的元素在内存中都是按下标由地址从低到高连续存放的,那么我们只需要知道首元素的地址,即可通过不断+1,+1遍历整个数组。代码示例如下:
#include <stdio.h>
void test(int* p, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ",*(p+i));
}
return;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
test(arr, sz);
return 0;
}
上面代码我是通过p+i 来实现遍历数组每个元素的,因为i++,所以就不需要去修改p的地址。
本次知识分享就到此结束了,谢谢观看!