Как удалить это предупреждение: второй параметр 'va_start не последний именованный аргумент?

У меня есть функция (см. ниже), которая выдает следующее предупреждение:

второй параметр 'va_start не последний именованный аргумент

Что это значит и как его удалить?

функция имеет следующий вид:

static int  ui_show_warning(GtkWindow *parent, const gchar *fmt, size_t size, ...)
    {
      GtkWidget *dialog = NULL;
      va_list args = NULL;
      int count = -1;
      char *msg = NULL;

      if((msg = malloc(size + 1)) == NULL)
        return -12;

      va_start(args, fmt);

      if((count = snprintf(msg, size, fmt, args)) < 0)
        goto outer;

      dialog = gtk_message_dialog_new(parent,
                      GTK_DIALOG_DESTROY_WITH_PARENT,
                      GTK_MESSAGE_WARNING,
                      GTK_BUTTONS_OK,
                      "%s", msg);
      (void) gtk_dialog_run(GTK_DIALOG(dialog));

      gtk_widget_destroy(dialog);

     outer: {
        if(args != NULL)
          va_end(args);

        if(msg != NULL)
          free(msg);

        return count;
      }
    }

Примечание: предложение по улучшению этого кода очень ценится.

Ответы

Ответ 1

Вам нужно использовать size вместо fmt:

va_start(args, size);

Это size, а не fmt, это последний параметр с явным именем (в отличие от параметров vararg, у которых нет имен). Вам необходимо передать последний именованный параметр в va_start, чтобы он мог определить адрес в памяти, с которой начинаются параметры vararg.

Ответ 2

second parameter of ‘va_start’ not last named argument

Что это значит и как его удалить?

Ваша функция имеет именованные параметры parent, fmt и size. C spec говорит, что вы должны всегда передавать последний именованный параметр в va_start для совместимости со старыми компиляторами. Поэтому вы должны пройти size, а не fmt.

(Но с современным компилятором он может работать в любом случае)

Ответ 3

Я думаю, что здесь возникает путаница: большинство людей имеют дело только с prinf-подобными функциями, которые имеют формат и varargs. и они думают, что им нужно передать имя параметра, которое описывает формат. однако va_start не имеет ничего общего с каким-либо форматом printf. это просто функция, которая вычисляет смещение в стеке, где начинаются безымянные параметры.