【问题标题】:How does work vararg function calling可变参数函数调用如何工作
【发布时间】:2014-01-03 10:44:53
【问题描述】:

我试图了解可变参数函数的工作原理。我读过man stdarg,我正在编写以下代码:

#include <stdarg.h>
#include <stdio.h>

int sum(int count, ...){
    va_list lst;
    va_start(lst, count);
    printf("First=%i,Second=%i,Third=%i, Fourth=%i, Fifth=%i\n",va_arg(lst,int),va_arg(lst,int),va_arg(lst,int),va_arg(lst,int),va_arg(lst,int));
}

int main(){
    sum(1,2,3,4);
}

编译并运行后,我有以下输入:

First=0,Second=134513840,Third=4, Fourth=3, Fifth=2

我不明白这一点。我预计 First=2, Second=3, Third=4 和 Fourth/Fifth 具有未定义的值,因为在函数调用后,参数从右到左推送到堆栈,va_arg(lst, int) 只返回一个指向堆栈中更深的元素的指针。

【问题讨论】:

  • 你对参数的数量“撒谎”。
  • 函数 (printf) 的参数没有定义的评估顺序(没有序列点),因此您的个人 va_arg 的评估没有特定的顺序,而不是从左到右.您应该首先将每个 va_arg 存储在一个变量(或数组)中,然后在 printf 调用中使用它。
  • 我认为大多数实现倾向于从右到左评估参数。试试#include &lt;stdio.h&gt; int main() {int n=1;printf("%d %d %d\n",n++,n++,n++);}。它很可能会打印3 2 1
  • 不过,未定义的行为是未定义的行为,不应依赖。

标签: c variadic-functions


【解决方案1】:

有一些小错误(第一个是我在评论中暗示的):

  • 函数参数(此处为 printf())以任何顺序(不一定是从左到右)进行计算。您必须首先将 va_arg 调用存储在变量或数组中,从而将序列点添加到程序中。
  • 在第一个参数中,您承诺提供 args 的数量 count,但没有提供。
  • 承诺返回int的函数。

像这样:

#include <stdarg.h>
#include <stdio.h>
int sum(int count, ...){
    if(count!=5) { printf("this version expects 5 variable args"); return 1; }
    va_list lst;
    va_start(lst, count);
    int a1 = va_arg(lst,int);
    int a2 = va_arg(lst,int);
    int a3 = va_arg(lst,int);
    int a4 = va_arg(lst,int);
    int a5 = va_arg(lst,int);
    va_end(lst); // added for cleanup
    printf("First=%i,Second=%i,Third=%i, Fourth=%i, Fifth=%i\n", 
         a1, a2, a3, a4, a5);
    return 0;
}
int main(){
    sum(5, 1,2,3,4,5);
    return 0;
}
    // prints: First=1,Second=2,Third=3, Fourth=4, Fifth=5

请注意,您的程序期望可变参数的数量为 5,但 var-arg-functions 的目的通常是让参数的数量可变,您可以这样写:

#include <stdarg.h>
#include <stdio.h>
int sum(int count, ...){
    va_list lst;
    va_start(lst, count);
    int i=0; for(; i<count; ++i) {
        printf("at %i is %i\n", i, va_arg(lst, int));
    }
    va_end(lst);
    return 0;
}
int main(){
    sum(5, 1,2,3,4,5);
    return 0;
}

【讨论】:

    【解决方案2】:

    这应该会产生所需的解决方案。

    #include <stdarg.h>
    #include <stdio.h>
    
    int sum(int count, ...){
        va_list lst;
        va_start(lst, count);
        int first=va_arg(lst,int),second=va_arg(lst,int),third=va_arg(lst,int),fourth=va_arg(lst,int),fifth=va_arg(lst,int);
        printf("First=%i,Second=%i,Third=%i, Fourth=%i, Fifth=%i\n",first,second,third,fourth,fifth);
    }
    
    int main(){
        sum(5,1,2,3,4,5);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-31
      • 2011-10-12
      • 2017-10-12
      • 2011-09-23
      相关资源
      最近更新 更多