输出参数:解决函数需要多个返回值。
#include <stdio.h>
//实现一个函数返回两个值(最大值与最小值)
int Max( int *arr,int len, int* min) //传min的地址,对父函数min的值进行修改
{
int max= 0;
*min = 0;
for(int i=0;i <len-1;i++)
{
if (arr[i] > arr[max])
{
max = i;
}
else
{
*min = i;
}
}
*min = arr[*min];
return arr[max];
}
int main()
{
int arr[] = {32,23,44,77,2,99,92};
int min ;
printf("max = %d\n",Max(arr,sizeof(arr)/sizeof(arr[0]),&min));
printf("min = %d \n",min);
return 0;
}
不定参函数:函数接受不同数目的参数(至少传递一个参数)。
可变参数列表通过 “stdarg”宏实现(一个类型 va_list 、三个宏 va_start、va_arg、va_end):
va_list: stadarg.h头文件声明的类型 va_list,例如:(va_list arg_ptr)声明 arg_ptr 变量为 va_list 类型的指针。
参数说明:type(要检索的参数的类型) arg_ptf(参数列表的指针) prev_param( ... 前面的第一个可选参数)
va_start : 用来初始化 arg_ptr 变量,把 arg_ptr 变量设置为指向 prev_param(可变参数部分的第一个参数)。
void va_start( va_list arg_ptr, prev_param );
va_arg : 用于访问参数列表的未确定的部分,这个宏接受两个参数(va_list 变量 、参数列表中下一个参数的类型)。返回当前参数。
type va_arg( va_list arg_ptr, type );
va_end : 检索完所有参数后,将 arg_ptr 置为空(释放arg_ptr)。
void va_end( va_list arg_ptr );
不定参函数应用:求平均值;求最大数;简单实现printf函数;
#include <stdio.h> #include <stdarg.h> void Max_List(int *rtval, ...) //输出列表中最大的数 { va_list va; int max = -1; va_start(va, rtval); while (1) { int val = va_arg(va, int); if (val < 0) { *rtval = max; break; } if (val > max) { max = val; } } va_end(va); } double Average(int n_values, ...) // 求列表的平均值,n_values为列表数个个数 { va_list va; int sum = 0; va_start(va, n_values); for (int i = 0; i < n_values; ++i) { sum += va_arg(va, int); } va_end(va); return sum * 1.0 / n_values; } void Print(const char *fomat, ...) //简单实现printf函数 { if (fomat == NULL) { return; } const char *p = fomat; va_list va; va_start(va, fomat); while (*p) { if (*p == '%') { if (*(p + 1) == 'd') { printf("%d ", va_arg(va, int)); } else if (*(p + 1) == 'c') { printf("%c ", va_arg(va, char)); } else if (*(p + 1) == 's') { printf("%s ", va_arg(va, char*)); } } p++; } va_end(va); } int main() { printf("%f\n", Average(2, 13, 14)); printf("%f\n", Average(3, 13, 15, 14)); printf("%f\n", Average(4, 13, 15, 14, 16)); int val = -1; //输出参数 Max_List(&val, 12, 34, 23, 15, 46, 35, 76, 56, 24, -1); printf("%d\n", val); Print("%d %c %s\n", 10, 'a', "hello"); return 0; }
函数指针:
函数指针:指向函数的指针变量(函数名通常存储该函数的地址)。
形式1:返回值 (*函数名)(参数列表)
形式2: typedef 返回值 (*新类型名) (参数列表)typedef int(*pfun)(int, int); // 定义 pfun 类型为 返回值为int、参数列表(int,int)的函数指针 int fun1(int a, int b) { printf("fun1\n"); return 10; } int main() { int(*p1)(int, int) = fun1; //p1为指向fun1的函数指针 p1(10, 20); //等价于fun1(10, 20); (*p1)(10, 20); //应用层面等价于p1(10, 20);(编译器最终还是翻译为地址) pfun p2 =fun1; //等价于 int(*p2)(int ,int) = fun1 ; p2(10,20); return 0; }
回调函数:通过函数指针调用函数。函数指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其他所指的函数时,就称其为回调函数。
例如:实现找出任意类型数据中的最大数,(改代码只实现了“半自动”需给出类类型的比较函数)
#include <stdio.h> typedef int(*Compare)(void*, void*); //viod* 任意指针类型,用于泛型转换 typedef int Element; //int 可以换任意类型,但许给转换类型的比较函数 Element GetMax(Element *arr, int len, Compare cp) { int max = 0; for (int i = 1; i < len; ++i) { if (cp(&arr[i], &arr[max])) // if(arr[i] > arr[max]) { max = i; } } return arr[max]; } int Maxint(void *a, void *b) // int类型的比较函数 { return *(int*)a > *(int*)b ? 1 : 0; } int MaxChar(void *a, void *b) //如:char类型的比较函数 { return *(char*)a > *(char*)b ? 1 : 0; } int main() { int arr[] = { 1, 2, 3, 4, 5, 6, 97, 3, 2, 8 }; int max = GetMax(arr, sizeof(arr) / sizeof(arr[0]), Maxint); printf("max = %d\n", max); return 0; }
转移表: 为了更好调用函数,将同类型的函数放在一个函数指针数组中,通过简单的数字或字符来查找函数。(转移表声明和初始化在同类型函数原型之后)
例如:
typedef double(*opter_fun)(int, int); //定义Opter_fun类型为 返回值为doubel类型,参数类表为(int,int)的函数指针 double my_add(int, int); double my_sub(int, int); double my_mux(int, int); double my_div(int, int); double my_sin(int, int); double my_cos(int, int); // 转移表 or 表驱动 opter_fun opter_fun_table[] = { my_add, my_sub, my_mux, my_div,my_sin, my_cos }; // 定义并初始化转移表