How does printf handle its arguments?
How d开发者_如何学Coes printf handle its arguments? I know that in C# I can use params
keyword to do something similar but I can't get it done in C ?
Such a function is called a variadic function. You may declare one in C using ...
, like so:
int f(int, ... );
You may then use va_start
, va_arg
, and va_end
to work with the argument list. Here is an example:
#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));
}
For more information, please see The C Book and stdarg.h.
This feature is called Variable numbers of arguments in a function. You have to include stdarg.h header file; then use va_list type and va_start, va_arg, and va_end functions within the body of your function:
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);
}
Then call your function like this:
print_arguments(3,1,2,3);
which will print out following:
I am first element of the list: 1
I am second element of the list: 2
I am third element of the list: 3
The way this is done in C is called "varargs". There's a tutorial for it here: http://c-faq.com/~scs/cclass/int/sx11b.html
Like others have said, printf uses va_args to function. It's a pretty cool exercise to write your own version of printf, if nothing else to verify that printf, unlike Pascal's writeln is not compiler magic. After you do that, you should walk away from it. Here is a blog article I wrote detailing why (the short answer is you can create bugs that may go undetected for a long time).
and just to complete the story gcc (not sure about other compilers) supports
#define FUNC(X,Y,...) wiz(X,Y, ##__VA_ARGS__)
to allow variadic macros
An add-on for answer completeness relating specifically to printf
in C:
printf
<stdio.h>
source code for convenience:
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);
We can see that the template described in above answers is satisfied:
- function declaration:
...
symbol emphasizes multiple arguments as input. va_list
variable creation, which automatically extracts the 'extra' input arguments .va_start
call which sets us at the address to start from.va_arg
call to actually use each argument. every call increments to the next argument. Will be used insidevfprintf
.va_end
macro to clean up and end the process. Similar in concept to 'free' in memory allocation.
精彩评论