介绍如何使用指针解决函数间的通信问题:
/*使用指针解决交换函数的问题*/
#include "stdio.h"
int main()
{
int x=5,y=10;
printf("x = %d , y= %d \n", x,y);
interchange(&x,&y); ///把地址发送给函数
printf("x = %d , y= %d \n", x,y);
return 0;
}
void interchange( int *u,int *v)
{
int temp;
temp = *u;
*u = *v;
*v = temp;
}
interchange(&x, &y);
**该函数传递的不是x和y的值,而是他们的地址,这意味着出现在interchange()原型和定义中的参数形式u和v将把地址作为他们的值。**因此因把他们声明为指针。
(开始没用指针,参数值没有改变的那是因为改变后的值在传回去后函数没有设置其该怎样输出,那之后用了一个输出的printf()函数使其将改变后的值输出,就能看到所编写的函数是对的,并且return main()使其返回主函数后进行不断循环
使用指针之后,可以理解成:编写的函数让两个值的地址进行交换,地址交换后,其实x y对应的值也就改变了,
但之前的那个代码:在函数中其实是交换了值的,但是没有传回主函数,并且主函数中的X,Y 的值是不变的,所以输出的值是没有交换的)
这一段理解不对;
void interchange (int * u, int * v) 接下来,在函数体中声明了一个交换值时必需的临时变量: int temp; 通过下面的语句把x的值储存在temp中: temp = *u; 记住,
这正是 我们需要的。不要写成这样: temp = u; / 不要这样做 /
上面那条语句赋给temp的是X 的地址(u的值就是X的地址)而不是X的值,函数要交换的是X的值,而不是他们的地址
这一段间接就说明了,上面理解不对的地方在哪:不加指针,赋给的就是地址不是值,但是要交换的是值不是地址。
与此类似,把y的值赋给x,要使用下面的语句: *u = *v; 这条语句相当于: x = y;
分析:需要一个函数交换x和y的值,把x和y的地址传递给函数,让编写的函数访问这两个函数,使用指针和*引用运算符,该函数可以访问储存在这些位置的值并且改变他们
可以省略ANSI C风格的函数原型中的形参名,如下所示: void interchange(int *, int *);
一般而言,可以把变量相关的两类信息传递给函数
如果这种形式的函 数调用,那么传递的是x的值:
function1(x);
如果下面形式的函数调用,
那么传递的是x的地址: function2(&x)
第一种形式要求函数定义中的形式参数必须是一个与X的类型相同的变量:
int function1(int num);
第二种形式要求函数定义中的形式参数必须是一个指向正确类型的指针:;
int function2(int * ptr );
如果要计算或处理值,那么使用第一种形式的函数调用;如果要在被调函数中改变主调函数的变量,采用第二种形式的函数调用
scanf就是这样:当程序要把一个值读入变量时
调用的是scanf("%d", &num)。scanf()读取一个值,然后把该值储存到指定的 地址上
指针让interchange()函数通过自己的局部变量改变main()中 变量的值
变量的名称、地址和变量的值之间关系密切
编写程序时,可以认为变量有两个属性:名称和值
计算机编译和加载程序后,认为变量也有两个属性:地址和值。地址就是变量在计算机内部的名称
在许多语言中,地址都归计算机管,对程序员隐藏,
例如,printf("%d\n", barn)打印barn的值,使用运算符即可获得储存在地址上的值。如果pbarn= &barn;,那么pbarn表示的是储存在&barn地址上的值。
使用& * 和指针可以操纵地址和地址上的内容
小结:
形式: 典型的ANSI C
函数的定义形式为:
返回类型 名称 (形参声明列表)
函数体
形参声明列表是用逗号分割的一系列变量声明。除形参变量外,函数的其他变量均在函数体的花括号之内声明。
传递值:
实参用于把值从主调函数传递给被调函数,如果变量a和b的值分别是5和2
那么调用: c = diff(a,b); 把5和2分别传递给变量x和y。5和2称为实际参数(简称实参),diff()函 数定义中的变量x和y称为形式参数(简称形参)。使用关键字return把被调 函数中的一个值传回主调函数。本例中, c接受z的值3。
如果希望把更 多的值传回主调函数,必须这么做。
函数的返回类型:函数的返回类型指的是函数返回值的类型,如果返回值的类型与声明的返回类型不匹配,返回值将被转换成函数声明的返回类型
函数签名:函数的返回类型和形参列表构成了函数签名。因此函数签名指定了传入函数的值的类型和函数返回值的类型
9.8 :关键概念:如果想用C编出高效灵活的程序,必须理解函数。把大型函数组织成若干函数非常有用,,甚至很关键,如果让一个函数处理一个任务,程序会更好理解,更方便调试,要理解函数是如何把信息从一个函数传递到另一个函数的,就是说,要理解函数参数和返回值的工作原理。另外,函数形参和其他局部变量都属于函数私有,因此,声明在不同函数中的同名变量是完全不同的变量,而且,函数无法直接访问其他函数中 的变量,这种限制访问保护了数据的完整性,但是,当确实需要在函数中访问另一个函数的数据时,可以把指针作为函数的参数。
本章小结:
函数可以作为组成大型程序的构建块。每个函数都应该有一个单独且定义好的功能。使用参数把值传给函数,使用关键字return把值返回函数。如果函数返回的值不是int类型,则必须在函数定义和函数原型中指定函数的类型,
如果需要在被调函数中修改主调函数的变量,使用地址或指针作为参 数。ANSI C提供了一个强大的工具——函数原型,允许编译器验证函数调 用中使用的参数个数和类型是否正确。 C 函数可以调用本身,这种调用方式被称为递归。一些编程问题要用递 归来解决,但是递归不仅消耗内存多,效率不高,而且费时