vlambda博客
学习文章列表

C语言指针变量作为函数参数

#include <stdio.h>void swap(int a, int b){ int temp; //临时变量 temp = a; a = b; b = temp;}int main(){ int a = 66, b = 99; swap(a, b); printf("a = %d, b = %d\n", a, b); return 0;}

运行结果:

a = 66, b = 99

从结果可以看出,a、b 的值并没有发生改变,交换失败。这是因为 swap() 函数内部的 a、b 和 main() 函数内部的 a、b 是不同的变量,占用不同的内存,它们除了名字一样,没有其他任何关系,swap() 交换的是它内部 a、b 的值,不会影响它外部(main() 内部) a、b 的值。

改用指针变量作参数后就很容易解决上面的问题:

#include <stdio.h>void swap(int *p1, int *p2){ int temp; //临时变量 temp = *p1; *p1 = *p2; *p2 = temp;}int main(){ int a = 66, b = 99; swap(&a, &b); printf("a = %d, b = %d\n", a, b); return 0;}

运行结果:

用数组作函数参数

数组是一系列数据的集合,无法通过参数将它们一次性传递到函数内部,如果希望在函数内部操作数组,必须传递数组指针。下面的例子定义了一个函数 max(),用来查找数组中值最大的元素:

#include <stdio.h>int max(int *intArr, int len){ int i, maxValue = intArr[0]; //假设第0个元素是最大值 for(i=1; i<len; i++){ if(maxValue < intArr[i]){ maxValue = intArr[i]; } }  return maxValue;}int main(){ int nums[6], i; int len = sizeof(nums)/sizeof(int); //读取用户输入的数据并赋值给数组元素 for(i=0; i<len; i++){ scanf("%d", nums+i); } printf("Max value is %d!\n", max(nums, len)); return 0;}

运行结果:

int max(int intArr[6], int len){ int i, maxValue = intArr[0]; //假设第0个元素是最大值 for(i=1; i<len; i++){ if(maxValue < intArr[i]){ maxValue = intArr[i]; } } return maxValue;}

int intArr[6]好像定义了一个拥有 6 个元素的数组,调用 max() 时可以将数组的所有元素“一股脑”传递进来。


读者也可以省略数组长度,把形参简写为下面的形式:

int max(int intArr[], int len){ int i, maxValue = intArr[0]; //假设第0个元素是最大值 for(i=1; i<len; i++){ if(maxValue < intArr[i]){ maxValue = intArr[i]; } } return maxValue;}

int intArr[]虽然定义了一个数组,但没有指定数组长度,好像可以接受任意长度的数组。


实际上这两种形式的数组定义都是假象,不管是int intArr[6]还是int intArr[]都不会创建一个数组出来,编译器也不会为它们分配内存,实际的数组是不存在的,它们最终还是会转换为int *intArr这样的指针。这就意味着,两种形式都不能将数组的所有元素“一股脑”传递进来,大家还得规规矩矩使用数组指针。

int intArr[6]这种形式只能说明函数期望用户传递的数组有 6 个元素,并不意味着数组只能有 6 个元素,真正传递的数组可以有少于或多于 6 个的元素。

需要强调的是,不管使用哪种方式传递数组,都不能在函数内部求得数组长度,因为 intArr 仅仅是一个指针,而不是真正的数组,所以必须要额外增加一个参数来传递数组长度。

C语言为什么不允许直接传递数组的所有元素,而必须传递数组指针呢?

参数的传递本质上是一次赋值的过程,赋值就是对内存进行拷贝。所谓内存拷贝,是指将一块内存上的数据复制到另一块内存上。

对于像 int、float、char 等基本类型的数据,它们占用的内存往往只有几个字节,对它们进行内存拷贝非常快速。而数组是一系列数据的集合,数据的数量没有限制,可能很少,也可能成千上万,对它们进行内存拷贝有可能是一个漫长的过程,会严重拖慢程序的效率,为了防止技艺不佳的程序员写出低效的代码,C语言没有从语法上支持数据集合的直接赋值。

除了C语言,C++JavaPython 等其它语言也禁止对大块内存进行拷贝,在底层都使用类似指针的方式来实现。