2

How can I pass many arguments to a C function? Assuming that I have this function:

void f(int n, char* a, char* b, ...)

I want an undefined number of char* arguments. How can I do so?

TheForbidden
  • 1,533
  • 4
  • 22
  • 30
  • 1
    You need to make a variadic function, see http://stackoverflow.com/questions/2735587/in-a-c-function-declaration-what-does-as-the-last-parameter-do – Joe Apr 05 '13 at 09:45

2 Answers2

6

What you needs is called variable number of argument functions, you can read from : 9.9. Variable numbers of arguments a good and essay tutorial.

A short theory in four points will help you to understand my code:

  1. the <stdarg.h> header file must be included, his introduces a new type, called a va_list, and three functions that operate on objects of this type, called va_start, va_arg, and va_end.
  2. va_start: is a macro to set arg_ptr to beginning of list ap of optional arguments
  3. va_arg: does is use this saved stack pointer, and extract the correct amount of bytes for the type provided
  4. va_end: is a macro to reset ap, After all arguments have been retrieved, va_end resets the pointer to NULL.

This theory is not enough but below an example (as you required) will help you to understand basic work-flow/ and steps: (read comment for each 4 steps)

//Step1: Need necessary header file
#include <stdarg.h>     
void f(int first, char* a, char* b, ...){   
    va_list ap;  // vlist variable
    int n;       // number 
    char aa,     
    int i;
    float f;
   //print fix numbers of arguments
    printf("\n %d, %s, %s\n", first, a, b);

   //Step2: To initialize `ap` using right-most argument that is `b` 
    va_start(ap, b); 

   //Step3: Now access vlist `ap`  elements using va_arg()
     n = va_arg(ap, int); //first value in my list gives number of ele in list 
     while(n--){
       aa = (char)va_arg(ap, int); // notice type, and typecast
       i = va_arg(ap, int);
       f = (float)va_arg(ap, double);   
       printf("\n %c %d %f \n", aa,i, f);
    }

    //Step4: Now work done, we should reset pointer to NULL
    va_end(ap); 
}
int main(){
    char* a = "Aoues";
    char* b = "Guesmi";
    f(2, a, b, 3, 'a', 3, 6.7f, 'b', 5, 5.5f, 'A', 0, 0.1);
    //         ^ this is `n` like count in variable list
    return 1;
}

Who does it runs:

~$ ./a.out 
 2, Aoues, Guesmi
 a 3 6.700000 
 b 5 5.500000 
 A 0 0.100000 

A brief explanation of my code will be helpful for future users:

  1. Actually function is fixed number of arguments followed by variable number of arguments. And right-most argument to function (in fixed argument list that is char* b in our function f()) uses just to initialized viable list ap.
  2. The function f() above fist reads n value that is 3 (read comment in main). In f(), while(n--) executes for three time and each time in loop using va_arg() macro we retrieves three values.
  3. If you notice I reads first two ints then a double, Where as I am sending char, int, float (notice in main where I call f()). this is because auto type promote in case of variable argument list. (read in detail from above lisk)

Her is one more useful link from MSDN: va_arg, va_end, va_start.

(let me know if you need more help regarding this)

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 1
    May I suggest, for the sake of demonstrating that the number of arguments passed is based around the `n=3` you pointed out in your code, that the three groups of arguments `'a',3,6.7f`, `'b',5,5.5f`, `'A',0,0.1` be in struct pointer form: `fun(2, a, b, 3, &(struct foo) { .aa='a', .i=3, .f=6.7f }, /* newline here */ &(struct foo) { .aa='b', .i=5, .f=5.5f }, /* newline here */ &(struct foo) { .aa='A', .i=0, .f=0.1f });` – autistic Apr 05 '13 at 10:25
  • @modifiablelvalue Yes , really nice suggestion man. But for OP I want to keep code bit simple. I included different datatypes because I want to demonstration that `char` promote up to `int`, `float` promote up to `double`. only. If you are writing a code like you suggesting then put that code on codepas and give me the link :)..thanks – Grijesh Chauhan Apr 05 '13 at 10:42
0

Use varargs (look this up yourself, the stuff the callee uses to read the args is in stdarg.h).

Note that there is no way for the callee to automatically determine the number of arguments actually passed. So for example it might be n, and you just have to trust the caller to get n right.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699