在纯C语言中,如何将数量可变的参数传递到函数中? 我如何通过C,而不是C++,将变量参数转换成函数? void foo(char* mandatory_param, char* optional_param, char* optional_param2...)

在纯C语言中,如何将数量可变的参数传递到函数中? 我如何通过C,而不是C++,将变量参数转换成函数? void foo(char* mandatory_param, char* optional_param, char* optional_param2...),c,function,C,Function,谢谢 /fmsf使用标准h 您需要使用va_list,然后使用宏va_start、va_arg和va_end 有关更多信息,请参见使用标准.h 您需要使用va_list,然后使用宏va_start、va_arg和va_end 有关更多信息,请参见听起来您正在寻找 听起来你在找我 阅读关于阅读关于在不直接支持可选参数的语言中,有几种方法可以实现类似的效果。我将按功能最少到最多的顺序列出: 创建同一函数的多个重载。我记得,在C语言中不能这样做 使用可变函数。只需谷歌一下: 我建议这样做:在C中创建一

谢谢

/fmsf使用标准h

您需要使用va_list,然后使用宏va_start、va_arg和va_end

有关更多信息,请参见使用标准.h

您需要使用va_list,然后使用宏va_start、va_arg和va_end


有关更多信息,请参见

听起来您正在寻找


听起来你在找我


阅读关于

阅读关于

在不直接支持可选参数的语言中,有几种方法可以实现类似的效果。我将按功能最少到最多的顺序列出:

创建同一函数的多个重载。我记得,在C语言中不能这样做

使用可变函数。只需谷歌一下:

我建议这样做:在C中创建一个params或args类或结构,如下所示:

然后使方法调用接受单个参数:

// untested
void foo(struct fooArgs * args)

这样,随着需要的变化,您可以在不破坏任何内容的情况下向fooArgs添加参数。

在一种不直接支持可选参数的语言中,有几种方法可以实现类似的效果。我将按功能最少到最多的顺序列出:

#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"
创建同一函数的多个重载。我记得,在C语言中不能这样做

使用可变函数。只需谷歌一下:

我建议这样做:在C中创建一个params或args类或结构,如下所示:

然后使方法调用接受单个参数:

// untested
void foo(struct fooArgs * args)
这样,随着需求的变化,您可以在不破坏任何内容的情况下向fooArgs添加参数

#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"

我有一个解决方案,在纯C中不使用VA_列表。但是,它只在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
}

我有一个解决方案,在纯C中不使用VA_列表。但是,它只在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
}


我想你指的是可变数量的参数。@mathepic:ty修复了这个问题我想你指的是可变数量的参数。@mathepic:ty修复了这个问题,可能是因为你所做的只是提供了一个链接,而不是将一些答案放在这里,并提供了一个外部参考以获取更多信息。提供了一个有用的,直接相关链接不应被视为否决投票的理由。使用链接+1。为什么要复制已经存在的东西?为什么要总结已经明确的内容呢?可能是因为他的答案在其他两个得票较高的人的1-2分钟内发布,而在提问的6分钟内发布。让我们看看,对于正确答案的质量,我们有多挑剔和忘恩负义-可能是因为你所做的只是提供了一个链接,而不是把一些答案放在这里,并提供了一个外部参考以获取更多信息。提供一个有用的、直接相关的链接不应被视为否决投票的理由。使用链接+1。为什么要复制已经存在的东西?为什么要总结已经明确的内容呢?可能是因为他的答案在其他两个得票较高的人的1-2分钟内发布,而在提问的6分钟内发布。让我们看看,对于正确答案的质量,我们有多挑剔和忘恩负义-PIt可能有助于读取示例中的多个参数,并显示使用sentinel停止,因为这与大多数语言不同。PIt可能有助于读取示例中的多个参数,并显示使用sentinel停止,因为这与大多数应为void的语言foostruct FooArgs*args不同,但是大多数人可能会在结构上使用typedef来简化事情。可能是因为问题在你的答案发布之前就已经澄清了,请注意,要询问传递可变数量的参数,而不是可选参数。你可能会考虑修改你的问题或移除它。+ 1的思考。并不是因为OP提出了一个非常具体的问题,所以用另一种方法解决类似问题的答案是不好的。Apollo的答案很有趣,甚至可以在调用链中使用。这应该是void foostruct FooArgs*args,但大多数人可能会在结构上使用typedef来简化事情。可能是因为在发布答案之前,问题已经澄清了,请注意,要询问传递可变数量的参数,而不是可选参数。你可能会考虑修改你的问题或移除它。+ 1的思考。并不是因为OP提出了一个非常具体的问题
用另一种方法解决类似问题的答案是不好的。Apollo的答案很有趣,甚至可以在调用链中使用。如果你打算否决投票,至少在评论中说为什么,而不是让我去想为什么我的答案在某些方面可能是错误的。哦,天哪,程序员有一种方法会使用varargs犯错误!他们一定很可怕!如果你要投否决票,至少在评论中说为什么,而不是让我去想为什么我的答案在某些方面可能是不正确的。哦,天哪,程序员有一种使用varargs犯错误的方法!他们一定很可怕!