【C语言天天练(四)】可变参数函数

可变参数函数指可以接受可变数量参数的函数。比如printf函数就是一个可变参数函数。

要完成可变参数函数的编写,需要用到定义于stdarg.h头文件中的一个类型va_list和三个宏va_start、va_arg、va_end。

注意:

1、可变参数必须从头到尾按照顺序逐个访问。如果在访问几个可变参数后想半途中止,这是可以的。但是,如果想一开始就访问列表中的参数,那是不行的。

2、由于参数列表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升。

3、参数列表中的省略号,它提示此处可能传递数量和类型未确定的参数。省略号只能出现参数表的尾部。

变长参数函数的关键在于 如何处理一个甚至连名字都没有的参数表。标准头文件<starg.h>中包含一组宏定义,它们对如何遍历参数表进行了定义。

va_list类型用于声明一个变量,该变量将依次引用各参数。

va_start宏将va_list声明的变量初始化为指向第一个无名参数的指针。在使用变量之前,该宏必须被调用一次。参数表必须至少包括一个有名参数,va_start将最后一个有名参数作为起点。

va_arg宏,调用该宏,该函数都将返回一个参数,并将声明的变量指向下一个参数。va_arg使用一个类型名来决定返回的对象类型、指针移动的步长。

va_end宏,该宏必须在函数返回之前调用,以完成一些必要的清理工作。

示例:

#include <stdarg.h>
#include <stdio.h>

/*
 *计算平均值
 */

float
average(int n_values, ...)
{
	va_list	var_arg;
	int		count;
	float	sum = 0;

	va_start(var_arg, n_values);	/*准备访问可变参数?       */

	for(count = 0; count < n_values; count+=1){
		sum += va_arg(var_arg, int);/*添加取自可变参数列表的值         ?*/
	}

	va_end(var_arg);				/*完成处理可变参数       */

	return sum/n_values;
}

void
main(int argc,  char **argv)
{
	printf("the average of 3 and 8 is %f\n", average(2, 3, 8));
	printf("the average of 3 and 8 and 11 is %f\n", average(3, 3, 8, 11));
	return;}

注意:C语言中的可变参数函数没有长度检查和类型检查,可能会被利用为攻击目标。设计函数时应先考虑替补方案。

【C语言天天练(四)】可变参数函数,布布扣,bubuko.com

时间: 2024-12-25 03:10:39

【C语言天天练(四)】可变参数函数的相关文章

【C语言天天练(十三)】printf、fprintf、sprintf和snprintf函数

#include <stdio.h> int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...); printf是标准的输出函数. fprintf传送格式化输

【C语言天天练(三)】函数

对于程序来讲,函数的地位是不言而喻的.下面先给出函数的定义,然后根据定义分析C语言中的函数. 函数定义: 类型 函数名(形式参数) 代码块 由定义可以看出函数主要包括四部分:函数类型.函数名.函数形参.函数代码块. 函数类型:指明了函数返回值的类型,是整数.浮点数.指针甚至是结构体等等.需要注意的两点:1.如果类型是void,则没有返回值.如果是void *型的返回值,那可以返回任意类型的指针,这是ANSI C标准定义的,void *可以是任意类型的指针.2.返回值的类型应该与函数定义的类型相同

【C语言天天练(十二)】命令行参数

C程序的main函数具有两个形参.第1个通常称为argc,它表示命令行参数的数目.第2个通常称为argv,它指向一组参数值. 指针数组:这个数组的每个元素都是一个字符指针,数组的末尾是一个NULL指针.argc的值和这个NULL值都用于确定实际传递了多少个参数.argv指向数组的第1个元素,这就是它为什么被声明为一个指向字符的指针的指针的原因.注意:通常第1个参数就是程序的名称. 示例: #include <stdio.h> int main(int argc, char **argv) {

【C语言天天练(二一)】内联函数

        引言:调用函数时,通常会因为建立调用.传递参数.跳转到函数代码并返回等花费掉一些时间,C语言的解决办法是使用类函数宏.在C99中,还提出了另外一种方法:内联函数.         内联函数:把函数变为内联函数将建议编译器尽可能快速地调用该函数,至于建议的效果则由实现来定义.因此,使函数变为内联函数可能会简化函数的调用机制,但也可能不起作用.内联函数是通过编译器来实现的,而宏则是在预编译的时候替换. 创建内联函数方法:在函数声明中使用函数说明符inline. 内联函数的特点: 1.

【C语言天天练(二十)】scanf函数详解

引言:scanf函数虽然是学习C语言时比较早就接触的一个函数,但在使用过程中,发现真正掌握它却并不容易.本文就通过各种例子来详细的总结一下该函数的各种用法,假设它的调用格式为 scanf("<格式化字符串>",<地址表>). 1.一般使用scanf函数时都是为某个变量赋值,不考虑它的返回值.但是任何函数都是需要返回的(即使返回类型用void,也可以认为只是调用了return语句,只是并没有返回什么东西而已),同样的scanf函数也是有返回的,它的返回值是成功读取

【C语言天天练(七)】回调函数

想要全面的了解一个概念,必须至少了解它的三点:它是什么.它有什么用.它在什么时候用.对于回调函数,同样从三个方面了解它. 1.什么是回调函数? 2.回调函数该如何使用?  3.回调函数在什么情况下使用? 答案一: 回调函数:见名知意,首先肯定的一点是它是一个函数,修饰词回调指的是程序员自己定义一个函数并实现它的程序内容,然后把这个函数的指针作为参数传递给其他函数(如系统函数)中,由其他函数(如系统函数)在运行时调用所实现的函数.函数是程序员自己实现的,但却是由其他函数(如系统函数)在运行时通过参

【C语言天天练(十四)】const关键字详解

const是一个C语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性,另外,了解const的作用,在看别人的代码时,对理解对方的程序有一定帮助. 1.const可以理解成是"只读变量"的限定词,从这里可以看出,const修饰的是变量,跟常量是不同的,常量是被编译器放在内存中的只读区域,当然也就不能够去修改它.而"只读变量"则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改.const就是用来限定一

C语言可变参数函数实现原理

一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本文地址:http://www.cnblogs.com/archimedes/p/variable-parameter.html,转载请注明源地址. 例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x200

C语言中的可变参数函数 三个点“…”printf( const char* format, ...)

第一篇 C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为: int printf( const char* format, ...); 它除了有一个参数format固定以外,后面跟的参数的个数和类型是可变的(用三个点“…”做参数占位符),实际调用时可以有以下的形式: printf("%d",i); printf("%s",s); printf("the number is %d ,string is:%s",