【问题标题】:In pure C how can I pass a variable number of parameters into a function?在纯 C 中,如何将可变数量的参数传递给函数?
【发布时间】:2010-06-12 16:10:50
【问题描述】:

如何使用 C 而不是 c++ 将可变参数传递(和访问)到函数中?

void foo(char* mandatory_param, char* optional_param, char* optional_param2...)

谢谢

/fmsf

【问题讨论】:

  • 我假设您的意思是可变数量的参数。
  • @mathepic:你解决了这个问题

标签: c function


【解决方案1】:

使用stdarg.h

您需要使用va_list,然后使用宏va_startva_argva_end

欲了解更多信息,请参阅http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.10.html

【讨论】:

  • 如果您要投反对票,请至少在评论中说明原因,而不是让我想知道为什么我的回答可能在某些方面不正确。
  • 哦,天哪,程序员使用可变参数有一种方法会出错!他们一定很糟糕!
【解决方案2】:

听起来您正在寻找varargs

#include <stdarg.h>
void foo(const char *fmt, ...)
{
  va_list argp;
  va_start(argp, fmt);
  int i = va_arg(argp, int);
  // Do stuff...
  va_end(argp);
}

【讨论】:

  • 阅读示例中的多个参数可能会有所帮助,并显示用哨兵停止,因为这与大多数语言不同
【解决方案3】:

【讨论】:

  • 可能是因为您所做的只是提供一个链接,而不是在此处放置一些答案并提供外部参考以获取更多信息。
  • 提供有用的、直接相关的链接不应被视为投反对票的理由。
  • +1 用于使用链接。为什么要复制已经存在的东西?为什么要总结已经明确的内容?
  • 也许是因为他的答案是在其他两个投票较高的人的 1-2 分钟内发布的,并且是在提出问题的 6 分钟内发布的。让我们看看,我们对正确答案的质量有多挑剔和忘恩负义? :-P
【解决方案4】:
#include <stdarg.h>

void do_sth (int foo, ...)
{
    int baz = 7;             /* "baz" argument */
    const char *xyz = "xyz"; /* "xyz" argument */

    /* Parse named parameters */
    va_list ap;
    va_start (ap, foo);
    for (;;) {
        const char *key = va_arg (ap, char *);
        if (key == NULL) {
            /* Terminator */
            break;
        } else if (strcmp (key, "baz") == 0) {
            baz = va_arg (ap, int);
        } else if (strcmp (key, "xyz") == 0) {
            xyz = va_arg (ap, char *);
        } else {
            /* Handle error */
        }
    }
    va_end (ap);

    /* do something useful */
}

do_sth (1, NULL);                             // no named parameters
do_sth (2, "baz", 12, NULL);                  // baz = 12
do_sth (3, "xyz", "foobaz", NULL);            // xyz = "foobaz"
do_sth (4, "baz", 12, "xyz", "foobaz", NULL); // baz = 12, xyz = "foobaz"

Variadic functions and arguments assignment in C/C++

【讨论】:

    【解决方案5】:

    在不直接支持可选参数的语言中,有几种方法可以达到类似的效果。我将按照从最不通用到最多的顺序列出它们:

    1. 为同一函数创建多个重载。我记得,你不能在 C 中做到这一点。

    2. 使用可变参数函数。谷歌一下:http://www.google.com/search?q=variadic+function+c

    3. 我建议这样做:创建一个“params”或“args”类(或 C 中的结构),如下所示:

    )

    // untested C code
    struct FooArgs {
        char * mandatory_param;
        char * optional_param;
        char * optional_param2;
        // add other params here;
    };
    

    然后让你的方法调用接受一个参数:

    // untested
    void foo(struct fooArgs * args)
    

    这样,随着需求的变化,您可以添加参数到 fooArgs 而不会破坏任何东西。

    【讨论】:

    • 应该是“void foo(struct FooArgs* args)”,但大多数人可能会在结构上使用 typedef 来简化事情。
    • 可能是因为问题已得到澄清(在您发布答案之前,请注意)询问是否传递“可变数量”而不是“可选”参数。您可以考虑修改或删除您的问题。
    • +1 开箱即用。并不是因为 OP 提出了一个非常具体的问题,所以使用另一种解决类似问题的方法的答案是不好的。 apollodude217 的回答很有趣,甚至可以用在调用链中。
    【解决方案6】:

    我有一个在纯 C 中不使用 VA_LIST 的解决方案。但是,它仅适用于 32 位。在这里,调用堆栈的每个参数根据其类型占用尽可能多的字节。可以创建大小超过 4 或 8 字节的结构体,因此只需对齐该结构体中的所有参数即可。

    int printf(void*,...);
    
    typedef struct{
      char p[1024];
    }P_CALL;
    
    int soma(int a,int b){
      return a+b;
    }
    
    void main(){
      P_CALL
        call;
      char
        *pcall=(void*)&call;
      int
        (*f)()=soma,
        res;
    
      *(int*)pcall=1;
      pcall+=sizeof(void*);
      *(int*)pcall=2;
      pcall+=sizeof(void*);
    
      res=f(call);
      printf("%d\n",res);//3
    }
    

    【讨论】:

      猜你喜欢
      • 2015-09-23
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 2013-09-21
      • 2017-09-28
      • 2015-01-05
      相关资源
      最近更新 更多