c语言如何获取函数可变参数的个数

开源中国董事会主席 发布于 2012/03/16 11:03
阅读 5K+
收藏 1
c语言如何获取函数可变参数的个数?
加载中
1
中山野鬼
中山野鬼

你可以参考我关于git配置环境的文章。我已经写过类似代码了。这里也贴出来

static void info_builtin(const char *info,va_list params){

	vreportf("info************: ",info,params);

}


void my_info(const char *info,...){
	va_list params;

	va_start(params, info);
	info_builtin(info, params);
	va_end(params);
	
}

如楼上说的,可变参是无法由编译器知道准确参数个数的。这需要函数代码之间相互约定。例如printf等格式化模式的函数。是通过格式化内的信息,来决定可变参的数量的。

例如一下两种情况

printf("%s : %d\n","test" ,1,2);
printf("%s : %d\n","test);

第一种情况,后面的可变参数目变多了,在实际执行时,2这个数字仍然会压到堆栈里,但是子函数不使用而已。如果 printf增加了 __attribute__((format 这类的定义,则GNU C会给与格式化检测,如果没有则不会有warning。但无论是否有warning,都不会导致程序崩溃或内存溢出问题。

第二种情况, 后面的可变参少了, 子函数会继续从堆栈里面再获取一个数据上来,很显然这个数据没有意义,因此这个空间根本就没有被用到过。同样不会引起程序崩溃和内存溢出。

 

说这么多,是希望你理解,C语言的可变参很强大,也非常特殊。就是根据实际掉函数时的情况,向堆栈里压数据,根据你代码里写的参数个数。你需要自己能够约束可变参的数量。通常的另一种实现方式,非格式化的,如下

void var_param_test(int type,...)

你可以由前面的TYPE来决定数量或者处理方式 ,由此完成函数和子函数之间的相互协同。

 

 

1
中山野鬼
中山野鬼
补充说一下,类似面向对象的重载等技术,在C语言的可变参面前真的很”浮云“,但是C语言的可变参用起来会很累,通常建议除了printf之类的格式化方式,不要使用可变参。
1
中山野鬼
中山野鬼

回楼上的。简单的减少代码量的方式用可变参并不是个好方法。我的例如如下:

1、代码内部实现和父函数之间很难有显式的约束说明,调用可变参函数的地方容易出错。我曾经用可变参实现C模拟C++的多态实现。例如,不同类型的加法,用一个函数入口实现。后来实际调用时,郁闷大了。每次都要看子函数的代码如何约束。

2、最终落到具有可变参函数内部,仍然存在一个针对不同参数的不同处理代码。要么循环针对每个变参在循环体内一一解析实现,要么分散成不同模块选择执行。但后者已经是函数指针动态跳转的思路了。

可变参并不能减少多少代码量(实际实现代码),可变参基本的用途是确实无法先验的知道函数之间传递的情况。

而且任何可变参的实现方式,在C下均可以用指针引入地址的方式实现。因为是等同的。等于你不用堆栈,而把要传的数据依次写到一个BUF内,将首地址传入。

开源中国董事会主席
开源中国董事会主席
恩 放弃这种方法
0
ChenQi
ChenQi

请参见stdarg.h中的三个宏va_start, va_arg, va_end.

这些宏无法判断实际存在的参数数量,也无法判断每个参数的类型。所以必须有一个命名参数传递进去。比如printf函数中的命名函数是字符串,它就不仅指定了参数数量,还指定了参数类型。

0
中山野鬼
中山野鬼

如果楼主真要搞清楚可变参,个人建议两个方式,如果都做了。基本上你会搞的非常清楚:

1、PC下自己模拟写一个fprintf的函数实现。不要调用所有的带格式化的库函数。只是最后生成一个字符串,你fwrite到文件里。

2、建议用ARM,编译后,看汇编。X86汇编不是RISC的,至少我的脑袋,不太容易理解。呵呵。

当然上面两个只是为了自己研究。平时写代码,不需要自己写printf类东西。库里有的除非你和我一样,写的代码是常驻TCM(类似L1 CACHE,但不是CACHE),才要考虑重新以压缩代码量和提高性能。

开源中国董事会主席
开源中国董事会主席
把一些重复性的操作放在一块儿来做。
开源中国董事会主席
开源中国董事会主席
其实 c 我仅仅是个入门者,我用来写php的动态链接库,我想实现可变参数的目的是,减少代码量
返回顶部
顶部