24

我有一个发出以下警告的函数(见下文):

'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;
      }
    }
4

4 回答 4

27

您需要使用size而不是fmt

va_start(args, size);

它是size,不是fmt,是最后一个具有显式名称的参数(与没有名称的可变参数相反)。您需要将最后一个命名参数传递va_start给它,以便它找出可变参数参数开始的内存地址。

于 2012-11-02T04:36:53.860 回答
8
second parameter of ‘va_start’ not last named argument

它是什么意思以及如何删除它?

您的函数具有命名参数parent和。C 规范说您必须始终将最后一个命名参数传递给,以便与旧编译器兼容。所以你必须通过,不是。fmtsizeva_startsizefmt

(但使用现代编译器,它可能仍然有效)

于 2012-11-02T04:38:58.447 回答
5

我认为这里有一个混淆:大多数人只处理具有格式和可变参数的类似prinf的函数。他们认为他们必须传递描述格式的参数名称。但是 va_start 与任何类型的 printf 格式无关。这只是一个计算未命名参数开始的堆栈上的偏移量的函数。

于 2013-05-14T19:33:01.347 回答
0

我在Ubuntu20.04上也遇到同样的问题,和点赞最多的答案相反,开头的代码,

void sprintf(char *str, char *fmt, ...) {
    va_list list;
    int i, len;
    va_start(list, 2);
    ...
}

然后,代码如下

void sprintf(char *str, char *fmt, ...) {
    va_list list;
    int i, len;
    va_start(list, fmt);
    ...
}

问题已解决。

于 2020-12-02T08:56:54.900 回答