C语言----指针与函数(高阶篇三十三)
传值与传址
父函数如果将变量的钥匙复制一份,再传给子函数,子函数就可以用钥匙开启这个变量,来进行操作。C语言中这种做法叫“传递指针”。
程序1
传址演示:设计一个函数,它可以交换任意两个变量的值。
// 33-1设计一个函数,它可以交换任意两个变量的值.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 #include <stdio.h> void swap(int *a1,int *a2) //交换函数 { int temp; temp = *a1; *a1 = *a2; *a2 = temp; } main() { //输入两个整数 int a, b; scanf("%d%d", &a, &b); //int *p1 = &a, *p2 = &b; swap(&a, &b); //swap(p1, p2); printf("%d\n%d\n", a, b); }
scanf与&
假设scanf函数定义如下:
void scanf(int *p1,int *p2)
{
*p1=从键盘读值;
*p2=从健盘读值;
}
main()
{
int a,b;
scanf(&a,&b);
printf("%d,%d",a,b);
}
printf为什么不用加&
void printf(int a,int b)
{
屏幕显示=a;
屏幕显示=b;
}
main()
{
int a,b;
printf(a,b);
}
数组名做函数参数
程序2
数组名做函数参数
// 33-2数组名做函数参数.c #include <stdio.h> //函数形参规定int arr[] 与 int arr[3] 与 int *arr意义是相同的 //int 表示数组元素个数 int sum(int *arr, int n) //操作数组时,定义形参: 数组名 数组元素个数 { int i = 0, s = 0; //计数器 总和 for ( ;i<n;i++) { s = s + *(arr + i); } return s; } main() { int a[3] = {1,2,3}; printf("%d\n", sum(a, 3)); }
注意:
※父子函数传递数组时,人们最先想到是使用
这样的方式传递:
fun(b[n]){…}
main()
{
int a[10];
fun(a[10]);
}
这是错误的理解。
※C语言规定:在函数的形式参数中,一旦发现int arr[]或int arr[3]这种数据类型定义,就统一编译为int *arr
因此,向子函数传递整个数组时,一定要附加一个参数来传递数组元素个数int n,定义成int arr[3]没有用,父函数照样可以传递一个int a[100]或是int a[2]进去。
※用数组名做参数有2个巨大的好处:
(1)再大的数组,只要传递2个参数,大大提高编程效率
(2)子函数不用返回值也可以批量修改父函数中的数据,真正做到“内存共享”。子函数相当于不用return,就可以返回值给父函数,还同时返回多个值。
因此,在函数间传递数组名,是经常使用的方法。
函数指针和函数返回指针
函数指针和函数返回指针这两种定义的区别:
函数指针(也叫指向函数的指针):
int (*pf)(int a); /*注意分号 int pf(int a); */
函数返回指针(也叫返回地址的函数),它的定义形式为:
int* fun(int a){…}
程序3
用函数找出一个数组中的最大数,返回它的地址
// 33-3用函数找出一个数组中的最大数,返回它的地址.c #include <stdio.h> int *find(int *arry,int n) //定义函数返回指针 { int *pmax; pmax = arry; // 数组首地址赋给 指针pmax for (int i = 1; i < n; i++) { if (*(arry + i) > *pmax) //比较值 pmax = arry + i; //赋值地址 } return pmax; //返回地址 } main() { int a[4] = { 15,67,89,13 }; //定义一个数组 int *pa = find(a,4); printf("%d\n", *pa); }
类型分解
※类型定义符出现在不同的标识符前,所表达的含义不同:
int i
出现在变量前,表示定义整型变量
int fun()
出现在函数前,表示函数返回int
int a[10]
出现在数组前,表示数组的每个元素都是整型
int *p
出现在指针前,表示定义的指针是整型
※变量之间通过指针或结构赋值或函数间传递参数时,类型必须相同,否则编译无法通过。
像int a;这样的类型定义,较好理解,表示a为int型,若是遇到复杂的类型,我们可以先找到变量或函数在程序头部的定义,将它的名称删除,就是它的类型。
下面几个是容易混淆的定义:
int* fun() 类型为int* ()
int *a[10] 类型为int*[10]
int (*pf)() 类型为int(*)()
int (*b)[10] 类型为int(*)[10 ]
练习
1、请编写函数,对传送过来的三个数选出最大和最小数,并通过形参传回调用函数。
// 33-4对传送过来的三个数选出最大和最小数,并通过形参传回调用函数.c #include <stdio.h> void fun(int a,int b,int c,int *nmax, int *nmin) { *nmax = a; if (b > *nmax) *nmax = b; if (c > *nmax) *nmax = c; *nmin = a; if (b < *nmin) *nmin = b; if (c < *nmin) *nmin = c; } main() { int a, b, c,m,n; scanf("%d%d%d", &a, &b, &c); fun(a,b,c,&m,&n); //传入 m n 的地址 printf("最大值%d\n最小值%d\n", m, n); }
2、请编写函数,其功能是对传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数。
// 传送过来的两个浮点数求出和值与差值,并通过形参传送回调用函数.c #include <stdio.h> //浮点数求和。 求差值。 void fun( float *sum , float *diff) { float a, b; a = *sum; b = *diff; *sum = a + b; *diff = a - b; } main() { float a, b; scanf("%f%f", &a, &b); fun(&a, &b); printf("和:%f\n差:%f\n", a, b); }