在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; }
运转后果:
a = 99, b = 66
挪用 swap() 函数时,将变量 a、b 的地址辨别赋值给 p1、p2,如许 *p1、*p2 代表的就是变量 a、b 自身,交流 *p1、*p2 的值也就是交流 a、b 的值。函数运转完毕后固然会将 p1、p2 烧毁,但它对内部 a、b 形成的影响是“耐久化”的,不会跟着函数的完毕而“恢恢复样”。
需求留意的是暂时变量 temp,它的感化特殊主要,由于履行*p1 = *p2;语句后 a 的值会被 b 的值掩盖,假如不先将 a 的值保管起来今后就找不到了。
数组是一系列数据的聚集,无法经过参数将它们一次性传递到函数外部,假如愿望在函数外部操作数组,必需传递数组指针。下面的例子界说了一个函数 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, maxValue; 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; }
运转后果:
12 55 30 8 93 27↙
Max value is 93!
参数 intArr 仅仅是一个数组指针,在函数外部无法经过这个指针取得数组长度,必需将数组长度作为函数参数传递到函数外部。数组 nums 的每一个元素多是整数,scanf() 在读取用户输出的整数时,请求给出存储它的内存的地址,nums+i就是第 i 个数组元素的地址。
用数组做函数参数时,参数也可以以“真正”的数组方式给出。例如关于下面的 max() 函数,它的参数可以写成下面的方式:
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++、Java、Python 等其它言语也制止对大块内存停止拷贝,在底层都运用相似指针的方法来完成。
本文出自 “11999725” 博客,请务必保留此出处http://12009725.blog.51cto.com/11999725/1843298
原文地址:http://12009725.blog.51cto.com/11999725/1843298