20

How does 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 ?

6 Answers 6

21

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Your example is wrong and doesn't work because it contradicts to the C syntax. Maybe you have made a typo and forgot underscore?
In addition, mentioning #include <stdarg.h> would be nice.
You're still short a few underscores, as psihodelia noted. The example does not compile.
11

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 

1 Comment

Did you mean print_arguments(3,1,2,3)?
8

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

Comments

7

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).

Comments

6

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

Comments

1

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:

  1. function declaration: ... symbol emphasizes multiple arguments as input.
  2. va_list variable creation, which automatically extracts the 'extra' input arguments .
  3. va_start call which sets us at the address to start from.
  4. va_arg call to actually use each argument. every call increments to the next argument. Will be used inside vfprintf.
  5. va_end macro to clean up and end the process. Similar in concept to 'free' in memory allocation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.