【问题标题】:va_arg always runs 4 timesva_arg 总是运行 4 次
【发布时间】:2015-11-13 20:03:35
【问题描述】:

我在 c 中学习 stdarg.h 我试图打印传递给函数的所有参数,但不知道有多少参数,但我还没有想出解决方案,在此期间发生了这种情况,无论我传递给 strtest 什么。 它总是打印 0. 1. 2. 3.

void strtest(char *fmt, ...){
    va_list argp;
    int i = 0;

    va_start(argp, fmt);

    while(va_arg(argp, char*))
        printf("%d\t", i++ );

    va_end(argp);
}

int main(int argc, char *argv[]){
    strtest("s");
    printf("\n");
    return 0;
}

【问题讨论】:

    标签: c variadic-functions


    【解决方案1】:

    没有标准机制可以告诉您传递给可变参数函数的参数数量。 printf() 之类的函数之所以有效,是因为它们可以通过检查格式字符串来确定参数的数量。

    【讨论】:

    • 查看此stackoverflow.com/questions/1688942/… 以了解操作方法。我不确定这是否符合标准,但取决于环境是否适合 OP。
    • @JJF 这个问题是关于参数类型,而不是参数数量。那里有具体的答案可以说明如何计算吗?
    • 查看带有 va_start(ap, count) 的部分; for(i=0 ; i
    • @JJF 这需要在不同的参数之前传递一个count 参数。
    • 哦,你是对的@Barmar。您可以将它们算作类似于我认为的 MSDN 示例 msdn.microsoft.com/en-us/library/kb57fad8.aspx。我再次怀疑它是标准的,但我很确定 Linux 也有类似的方式。干杯。
    【解决方案2】:

    这是一个示例,展示了一种传递未知数量参数的方法。

    #include <stdio.h>
    #include <stdarg.h>
    
    void print (char *first, ...)
    {
        va_list argptr;
        char *next;
        va_start (argptr, first);
        next = first;
        while (next) {
            printf ("%s\n", next);
            next = va_arg(argptr, char*);
            }
        va_end (argptr);
    }
    
    int main(void)
    {
        print("hello","world", NULL);      // NULL as sentinel
        return 0;
    }
    

    程序输出

    hello
    world
    

    也许您可以使用 int 参数来适应您的需求。

    【讨论】:

      【解决方案3】:

      这是 ISO 9899 WG14 n1256 中 stdarg.h 的定义

      头文件声明了一个类型并定义了四个宏,用于推进 通过被调用函数不知道其数量和类型的参数列表 什么时候翻译的

      您必须将参数的数量以及可能的类型传递给调用者。这不必通过直接传递参数的数量来完成,还有其他方法,例如 printf 中使用的方法。

      【讨论】:

      • 或包含NULL sentinel。
      • 或解析类似格式字符串的功能(不需要是格式字符串)
      • @WeatherVane NULL 哨兵只有在所有参数都是相同类型的指针时才有效。
      • @Barmar 我不认为NULL 是特定于类型的,但我发布了一个答案,其中它们都是相同的类型。
      • @WeatherVane NULL 是一个 void 指针,并且在某些系统中 void 指针的表示形式与 int 指针不同。 c-faq.com/null/machexamp.html
      【解决方案4】:

      你可以像这样向函数传递一个哨兵

      strtest("s", (char*)0);
      

      这样函数可以注意到它位于参数列表的末尾。

      【讨论】:

        【解决方案5】:

        如果您查看 stdarg 的手册页,va_arg 包含此文本

        如果没有下一个参数,或者类型与 实际下一个参数的类型(根据 默认参数提升),会发生随机错误。

        除非您使用 NULL 作为最后一个参数调用 strtest,否则 va_arg 将继续读取,直到遇到使其停止的东西。想想你现在正在做的事情等同于读取一个超出其边界的数组。

        无论如何,我很惊讶它运行了 4 次。我本来希望计数等于您传递给 strtest 的 args 数量加上 2 或更多。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-19
          • 1970-01-01
          • 2015-03-29
          • 2013-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多