ziKmouT
ziKmouT

Reputation: 205

Variadic function and va_arg : variabilizing the type to be printed

I am trying to recode a printf function so I need to use va_arg since printf is a variadic function.

The thing is, when I want to print out the arguments of my_printf, they can be %i (int) or %s (char *) if we take these two basic possibilities.

So when I go through my va_list ap, I tried to put a variable in the va_arg function so I can change the type to be written, like this:

char *str = NULL;
str = ft_set_my_types(flags[cur_arg]);          
ft_putstr(va_arg(ap, str));

with my function ft_set_my_types being something like:

char *ft_set_my_types(char *flags)
{
    char **tab = NULL;

    tab = ft_alloc_mem2(2, 15); /* this function malloc a tab */
    char a = 65;

     /* the example here is only with two types of variables */
     /* I am sending flags %s in my example which correspond to "char *" */

    tab['s'] = "char *";
    tab['d'] = "int ";

    size_t len = ft_strlen(flags) - 1;
    while (a < 123)
    {
        if (a == flags[len])
            break ;
        else
            a++;
    }
    return (tab[a]);
}

The "char *flags" being everything between the "%" and the flag (included) of my_printf.

The problem is: when I compile it does not understand my tab['s'] as char * but as "char *" so I get this error:

ft_print.c:63:25: error: unknown type name 'str'
                        ft_putstr(va_arg(ap, str));
                                             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.2/include/stdarg.h:35:50: note:
      expanded from macro 'va_arg'
#define va_arg(ap, type)    __builtin_va_arg(ap, type)
1 error generated.

Could you help me to figure out how I can insert my variable *str in this va_arg function?

Upvotes: 0

Views: 502

Answers (1)

John Bollinger
John Bollinger

Reputation: 181339

C is statically typed. All data types are determined at compile time. You cannot obtain the data type for a declaration by calling a function.

Instead, to handle variadic arguments whose type is not known until run time, you must branch based on the selected data type, via a switch statement or an if/else if/else nest. In each alternative, use the va_arg macro to obtain the argument, with the appropriate static type handled by that alternative. You may be able to perform the type-specific processing in helper functions, if you like.

For example,

/* ... */
switch (field_code) {
    case 'i':
        do_something_with_int(va_arg(ap, int));
        break;
    case 's':
        do_something_with_string(va_arg(ap, char *));
        break;
    default:
        handle_error();
        break;
}
/* ... */

Note that the second argument to va_arg is the type itself, not a string representation of it.

Upvotes: 5

Related Questions