va_args in c from <stdarg.h> does not work correctly

60 Views Asked by At

I am trying to write my own printf function in c, but I faced with a problem, when I want to call my functions with this arguments :

ft_printf ("Characters: %c %c\n",'s','e');

instead of getting 's' 'e' , I got 's' 's'. It looks like it does not go through all arguments,

this is my function :

    static int get_args(va_list args, char format)
    {
  if(format == 'c')
      return(print_char(va_arg(args,int))); //here I called va_args to retrieve args
    }
   

 int    ft_printf(const char *format, ...)
    {
        va_list args;
        int i;
        int len;
        
        len = 0;
        i = 0;
        
        va_start(args,format);
        while (format[i])
        {
            if (format[i] == '%')
            {
                      len += get_args(args, format[i + 1]);
                i++;
            }
            else
            {
                      write(1,&format[i],1);
                      len++;
                }
            i++;
        }
        va_end(args);
        return len;
    
    }

int main()
{
    printf ("Characters: %c %c \n",'s','e');
    ft_printf ("Characters: %c %c\n",'s','e');
    
    return 0;
}
1

There are 1 best solutions below

1
Artyer On BEST ANSWER

After passing args to get_args() and calling va_arg inside, the value of the original args in ft_printf() is indeterminate†, and you can only va_end it.

However, if you pass it by reference (with a pointer), it properly updates args in the original function:

static int get_args(va_list *args, char format)
{
  if (format == 'c')
      // here I called va_args to retrieve args
      return print_char(va_arg(*args, int));
}


int ft_printf(const char *format, ...)
{
    // ...
    len += get_args(&args, format[i + 1]);
    // ...
}

† On some platforms, va_list is a type like an integer or pointer, so get_args receives a copy and va_arg can't update the original. On other platforms, it's an array type, so the function parameter becomes a pointer so it's automatically passed "by reference" and the original value is updated. You appear to be using a platform with the former type, where args in ft_printf isn't modified.