函数输出参数、不定参函数(printf不定参机制)、函数指针(回调函数、转移表)(c语言)

输出参数:解决函数需要多个返回值。

#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
}; // 定义并初始化转移表

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值