How varargs works in C. (Python has *args, **kwargs)

Let’s think about when you were learning programming language first time.

Most tutorials teach you how to print “Hello World”.

In C,

#include <stdio.h>
int main(int argc, char** argv) {
    printf("Hello World!\n");
    return 0;
}

You guys all know that. Every people learn that code.

But in depth of printf (in the man page of printf),

#include <stdio.h>

int printf(const char *restrict format, ...);
int fprintf(FILE *restrict stream,
            const char *restrict format, ...);
int dprintf(int fd, const char *restrict format, ...);
int sprintf(char *restrict str,
            const char *restrict format, ...);
int snprintf(char *restrict str, size_t size,
             const char *restrict format, ...);

There are much of “…” s!

How can we handle that varargs?

Following “stdarg.h” manual, You can easily find below sentence.

The called function must declare an object of type va_list which
is used by the macros va_start(), va_arg(), and va_end().

And I should implement this like that.

void some_func(int num, ...) {
    va_list ap;
    va_start(ap, &num);
    // Some logic in your program using va_arg()
    va_end(ap);
}

OK, va_list is type of varargs that actually stores varargs informations.

So how can I count number of varargs?

No, You can’t.

Before you use varargs function, You have to pass number of varargs or put NULL to end of arguments.

There are two ways to handle varargs.

First is using format string like a printf(“%d %d %d %d”, 1, 2, 3, 4);

Second is using sentinel value like right before I explained. That’s way is used *exec() families. (execl)

OK, Let’s implement that!

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void print_all(char *arg, ...) {
    va_list ap;
    va_start(ap, arg);

    printf("new args: %s\n", arg);
    char *new;

    while ((new = va_arg(ap, char*)) != NULL) {
        printf("new args: %s\n", new);
    }
    va_end(ap);
}

int main() {
    print_all("hi", "hello", "bye", "really bye", NULL);
    return 0;
}

If you run `print_all` function, that will print all of arguments before while loop meets NULL.

Even if you don’t know how many args are in function, you know when to stop if function got NULL.

This is second way to implement varargs and catching the stop point.

Code에 게시되었습니다