【发布时间】:2011-01-26 20:36:52
【问题描述】:
printf 如何处理它的参数?我知道在 C# 中我可以使用 params 关键字来做类似的事情,但我无法在 C 中完成它?
【问题讨论】:
printf 如何处理它的参数?我知道在 C# 中我可以使用 params 关键字来做类似的事情,但我无法在 C 中完成它?
【问题讨论】:
这样的函数称为variadic function。您可以使用... 在 C 中声明一个,如下所示:
int f(int, ... );
然后您可以使用va_start、va_arg 和va_end 来处理参数列表。这是一个例子:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
void f(void);
main(){
f();
}
int maxof(int n_args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
更多信息请查看The C Book和stdarg.h。
【讨论】:
#include <stdarg.h>也不错。
此功能称为函数中的可变参数数。您必须包含 stdarg.h 头文件;然后在函数体中使用 va_list 类型和 va_start、va_arg 和 va_end 函数:
void print_arguments(int number_of_arguments, ...)
{
va_list list;
va_start(list, number_of_arguments);
printf("I am first element of the list: %d \n", va_arg(list, int));
printf("I am second element of the list: %d \n", va_arg(list, int));
printf("I am third element of the list: %d \n", va_arg(list, int));
va_end(list);
}
然后像这样调用你的函数:
print_arguments(3,1,2,3);
将打印出以下内容:
I am first element of the list: 1
I am second element of the list: 2
I am third element of the list: 3
【讨论】:
print_arguments(3,1,2,3)?
在 C 中完成此操作的方式称为“可变参数”。这里有一个教程:http://c-faq.com/~scs/cclass/int/sx11b.html
【讨论】:
正如其他人所说,printf 使用 va_args 来运行。编写自己的 printf 版本是一个非常酷的练习,如果没有其他方法可以验证 printf,与 Pascal 的 writeln 不同,它不是编译器魔法。在你这样做之后,你应该远离它。这是我写的blog article,详细说明了原因(简短的回答是您可以创建可能长时间未被发现的错误)。
【讨论】:
只是为了完成 gcc(不确定其他编译器)支持的故事
#define FUNC(X,Y,...) wiz(X,Y, ##__VA_ARGS__)
允许可变参数宏
【讨论】:
一个与 C 语言中的 printf 相关的答案完整性插件:
printf<stdio.h>source code为方便起见:
20 #include <libioP.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #undef printf
25
26 /* Write formatted output to stdout from the format string FORMAT. */
27 /* VARARGS1 */
28 int
29 __printf (const char *format, ...)
30 {
31 va_list arg;
32 int done;
33
34 va_start (arg, format);
35 done = vfprintf (stdout, format, arg);
36 va_end (arg);
37
38 return done;
39 }
40
41 #undef _IO_printf
42 ldbl_strong_alias (__printf, printf);
43 /* This is for libg++. */
44 ldbl_strong_alias (__printf, _IO_printf);
我们可以看到上面的答案描述的模板是满足的:
... 符号强调多个参数作为输入。va_list 变量创建,自动提取“额外”输入参数。va_start 调用,它将我们设置为开始的地址。va_arg 调用以实际使用每个参数。每次调用都会递增到下一个参数。将在vfprintf 内部使用。va_end 宏清理并结束进程。在概念上类似于内存分配中的“免费”。【讨论】: