指针作为函数参数,C语言指针作为函数参数详解
# include stdio.h void Swap(int a, int b); //函数声明 int main(void) int i = 3, j = 5; Swap(i, j); printf( i = %d, j = %d/n , i, j); return 0; void Swap(int a, int b) int buf; buf = a; a = b; b = buf; return; }
大家想一下,执行这个程序是否能互换 i 和 j 的值?不能!i 还是3,j 还是5。
因为实参和形参之间的传递是单向的,只能由实参向形参传递。被调函数调用完之后系统为其分配的内存单元都会被释放。所以虽然将 i 和 j 的值传给了 a 和 b,但是交换的仅仅是内存单元 a 和 b 中的数据,对 i 和 j 没有任何影响。
为什么不用 return 语句? 因为 return 语句只能返回一个值,并不能返回两个值。 将 printf 放在被调函数中不就行了吗? 我们的目的是互换内存单元 i 和内存单元 j 中的数据。而 printf 的功能仅仅是将结果输出,并不能改变数据处理的本质,互换的还是单元 a 和单元 b 中的数据。
以上传递方式叫作拷贝传递,即将内存 1 中的值拷贝到内存 2 中。拷贝传递的结果是:不管如何改变内存 2 中的值,对内存 1 中的值都没有任何影响,因为它们两个是不同的内存空间。
所以要想直接对内存单元进行操控,用指针最直接,指针的功能很强大。
# include stdio.h void Swap(int *p, int *q); //函数声明 int main(void) int i = 3, j = 5; Swap( i, printf( i = %d, j = %d/n , i, j); return 0; void Swap(int *p, int *q) int buf; buf = *p; *p = *q; *q = buf; return; }
输出结果是:
i = 5, j = 3
此时实参向形参传递的不是变量 i 和 j 的数据,而是变量 i 和 j 的地址。其实传递指针也是拷贝传递,只不过它拷贝的不是内存单元中的内容,而是内存单元的地址,这就是天壤之别了。拷贝地址就可以直接对地址所指向的内存单元进行操作,即此时被调函数就可以直接对变量 i 和 j 进行操作了。有人会说: 被调函数用完就释放了,不就把 i 和 j 都释放了吗? 不是的,当函数调用完之后,释放的是 p 和 q,不是 i 和 j。p 和 q 中存放的是 i 和 j 的地址。所以 p 和 q 被释放之后并不会影响 i 和 j 中的值。前面讲过,修改指针变量的值不会影响所指向变量中的数据。只不过它们之间的指向关系没有了而已。
此外需要注意的是,形参中变量名分别为 p 和 q,变量类型都是 int* 型。所以实参 i 和 j 的地址 i 和 j 是分别传递给 p 和 q,而不是传递给 *p 和 *q。
函数参数传指针和传数据的区别
综上所述,如果希望在另外一个函数中修改本函数中变量的值,那么在调用函数时只能传递该变量的地址。如果这个变量是普通变量,那么传递它的地址就可以直接操作该变量的内存空间。
那么,是不是要定义一个指针变量指向它然后传递这个指针变量呢?不用多此一举。比如有一个 int i; ,如果想传递i的地址那就直接传递 i 就行了,不用专门定义一个指针变量指向它,然后再传递这个指针变量。
如果要传递的变量本身就是一个指针变量怎么办?如果要操作该指针变量所指向的内存空间是不是要传递该指针变量的地址呢?
指针变量本身就是地址,本身就是指向那个内存空间的,所以直接把它传过去就行了。除非你要改变那个指针变量里面存放的地址,即你要改变指针变量的指向,那么你就必须要传递指针变量的地址。
此外,传指针和传数据相比还有一个好处就是节约内存。我们知道,传数据拷贝的是内存单元的数据,如果数据很多的话拷贝过来都要为它们分配内存。而传指针的话只需要传递 4 字节的地址就行了。而且传数据非常消耗效率,为形参分配内存需要时间,拷贝需要时间,最后结束了返回还是需要时间。前面说过,return 时系统会先自动创建一个临时变量来存放返回的值。所以传数据时很消耗效率,而传指针就是为了提高效率。
事实上,在实际编程中我们都是传递指针!往往只有满足下面这两个条件的时候我们才会直接传递数据而不是传递指针,而且这两个条件缺一不可:
此时不是不能用指针,当然也可以用指针,只是没有必要。
以后在使用函数的时候,只要函数的参数不满足上面这两个条件,那么全部都用指针。此外需要注意的是,数组名本身就是地址,所以如果传递数组的话直接传递数组名就行了。接收的形参可以定义成数组也可以定义为同类型的指针,这点后面再讲。
21517.html
相关文章
- C语言开发简单的学生成绩管理系统(附源码)
- 蓝桥杯 名次判断(详解)----------------C语言—菜鸟级
- 蛇行矩阵 蛇形填数 回形取数 蛇行系类(C语言详解+图解)
- 彻底搞定C语言指针(精华版)详解编程语言
- [C语言] 数据结构-逻辑结构和物理结构详解编程语言
- C语言之冒泡排序详解编程语言
- C语言之带有返回值的函数详解编程语言
- C语言之循环结构 for(二)详解编程语言
- C语言_指针和数组的几种访问形式详解编程语言
- 指针变量的初始化,C语言指针变量初始化详解
- 多级指针(二级指针),C语言多级指针的用法详解
- 函数指针及其定义和用法,C语言函数指针详解
- C语言左值与右值详解
- 数组指针和指针数组的区别,C语言数组指针和指针数组区别详解
- setjump和longjump函数及使用注意事项,C语言setjump和longjump函数详解
- C语言将数组作为函数参数
- Linux:基于C语言的操作系统(linux基于什么语言)
- Linux下如何高效调试C语言程序?(linux调试c语言程序)
- MySQL添加事务的C语言实现(c mysql添加事务)
- C语言快速构建MySQL实体类(c mysql 实体类)
- C语言实现导入Oracle数据库(c 批了导入oracle)
- C语言与Oracle配合,实现自增发展(c oracle 自增)
- C语言中#define与typedef的互换细节详解