应用场景一
函数返回多个值,某些值就只能通过指针返回;传入的参数实际上是需要保存带回的结果的变量。
交换两个变量的值
#include <stdio.h>
void swap(int *pa, int *pb);
int main()
{
int a = 5;
int b = 6;
swap(&a, &b);
printf("a=%d, b=%d\n", a, b);
return 0;
}
void swap(int *pa, int *pb)
{
int t = *pa;
*pa = *pb;
*pb = t;
}
求最大最小值
#include <stdio.h>
void minmax(int a[], int len, int *min, int *max);
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10};
int min, max;
minmax(a, sizeof(a)/sizeof(a[0]), &min, &max);
printf("min=%d, max=%d\n", min, max);
//1 printf("&min=%d, &max=%d\n", &min, &max);
return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
//2 printf("%d\n", sizeof(a));
//3 printf("%d\n", sizeof(a[0]));
// 这两句告诉你为什么数组传进函数不能直接用sizeof求长度,
// 而需要另外定义一个变量表示长度,在主函数中去求。
// 原因在于数组是以指针的形式传进函数,
// 因此sizeof(a)不是数组a的长度,而是数组a的地址的长度。
// 64位系统中地址长度为8,32位系统中地址长度为4
// a[0]可以看作一个int型变量,因此sizeof(a[0])=4
int i;
*min = *max = a[0];
for ( i=1; i<len; i++)
{
if ( a[i]< *min)
{
*min = a[i];
}
if ( a[i]> *max)
{
*max = a[i];
}
}
//4 printf("*min=%d, *max=%d\n", *min, *max);
//5 printf("inner min=%d, inner max=%d\n", min, max);
}
注释代码2/3:解释为什么数组传进函数后不能直接用sizeof(a)/sizeof(a[0])来求数组长度,而往往需要另外定义一个变量len来储存数组的长度;
注释代码1/4/5(对指针的理解):可以帮助更好的理解指针,在子函数中,min与max表示的是最小值与最大值的地址,*min 与 *max则表示最大最小值;在主函数中,min与max表示的是最小值与最大值,&min与&max则表示其地址。
因此,传入函数的是变量的地址,函数中指针的作用实际上是对变量的地址进行操作,改变了主函数中变量的地址值,从而交换变量的值。如果不使用指针,在子函数中只能直接交换变量的值,而此操作对于主函数中的变量是无效的。因为函数的参数传递,只能对值进行操作,不能对变量进行操作。
应用场景二
函数返回运算的状态,结果通过指针返回。编写函数过程中一种常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错:例如-1和0(此时便不需要指针);而有的时候-1和0也是程序运行可能出现的结果(例如做除法),那么这时就不能用以上方法,而需要用函数返回值来表示函数状态(是否出错),再另外定义一个指针来返回运算结果。
除法函数
#include <stdio.h>
int divide(int a, int b, int *result);
int main()
{
int a = 5;
int b = 3;
int c;
if (divide(a, b, &c))
{
printf("%d/%d=%d\n", a, b, c);
}
return 0;
}
int divide(int a, int b, int *result)
{
int ret = 1;
if ( b == 0)
{
ret = 0;
printf("除数不能为0\n" );
}
else
{
*result = a/b;
}
return ret; //如果除法成功,返回1;否则返回0
}
本函数是进行除法的函数,由于除数不能为0,因此需要首先对除数做判断,本函数用返回值表示运算的状态(即能否成功相除):返回值为0表示除数为0,返回值1表示可以正常相除;另外,需要定义一个指针变量,来保存相除的结果(的地址)。