【问题标题】:Second argument of "va_start"“va_start”的第二个参数
【发布时间】:2014-07-18 20:57:58
【问题描述】:

对于以下代码:

void fun(char *msg, int n, int m, ...) {
    va_list ptr;
    va_start(ptr, m);  // Question regarding this line

    printf("%d ", va_arg(ptr, int));
}

函数调用如下:

fun("Hello", 3, 54, 1, 7);

我的问题是关于上面评论的那一行。我尝试了该行的以下三个版本:

va_start(ptr, msg);
va_start(ptr, n);
va_start(ptr, m);

在所有三种情况下,我都得到“1”作为输出。 From what I have readva_start 的第二个参数应该是函数fun() 的参数列表中的最后一个参数,即va_start(ptr, m); 应该是正确的调用。那么为什么我在所有三种情况下都得到相同的输出。

[我在 Ideone 上运行程序,如果这有什么后果的话。]

【问题讨论】:

  • 如果我不得不猜测,其他两个是未定义的行为。
  • 似乎最相关的文本是参数parmN是函数定义的可变参数列表中最右边的参数的标识符(就在...之前的那个)。 i> 这在 C 和 C++ 中是一样的。我认为不遵循这是未定义的行为。
  • 我会假设您对 va_start 的特定实现并不真正需要第二个参数来完成它的工作,因此只是忽略它并且总是做正确的事情。但严格来说,用除最后一个参数之外的任何其他参数调用它当然是未定义的行为。

标签: c++ c variadic-functions


【解决方案1】:

根据 C 标准,您显示的前两个调用是未定义的行为;只有传递最后一个命名参数的调用是正确的。但是,您在 gcc 上会获得良好的行为,因为 gcc 编译器会忽略 va_start 的第二个参数,使用不同的技术来查找参数列表的结尾:

传统的实现只需要一个参数,即存储参数指针的变量。 va_start 的 ISO 实现需要额外的第二个参数。用户应该在这里写函数的最后一个命名参数。 但是,va_start 不应使用此参数。找到命名参数结尾的方法是使用下面描述的内置函数 {link}

【讨论】:

  • @Deduplicator 是的,你是对的 - 我的意思是前两个。我进行了编辑,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多