如果在C中使用va_list不存在额外参数时如何设置默认值

时间:2012-01-13 01:17:00

标签: c variadic-functions

当尝试编写一个没有给出额外参数时具有默认值的函数时,我遇到了问题。我已经尝试检测给定的唯一参数是否等于NULL(如其他答案所示)但它似乎对我没有用。

此函数的实际实现采用结构并将其添加到第二个参数中给出的链接列表中。如果没有给出第二个参数,我希望它将它添加到先前已定义的默认全局链表中。

下面是一个使用int类型参数的简单版本,但我想要做的原则是相同的:

/* appropriate headers... */

void test(int a, ... ) {

   int b;

   va_list args;
   va_start(args,a);

   b = va_arg(args,int);

   if (b == NULL) { // check if no argument is given and set default value
       b = 0; 
   } // if b != NULL then it should be set to the value of the argument
   va_end(args);

   printf("%d %d\n",a,b);
}

int main() {
   test(1);
   test(1,1);
   return 0;
}

然而,这给出了输出:

1 *random memory address*
1 1

我想要的输出应该是第一行

1 0

如果我不能使用这种方法,那么有没有人有任何想法如何实现我想要的?提前谢谢。

3 个答案:

答案 0 :(得分:4)

只有va_list无法做到你想做的事。

您可以使用宏和__VA_ARGS__强制某个参数在您的参数列表中最后显示为“终结符”。即:

#define TEST(a, ...) Test(a, __VA_ARGS__, 0)

请注意,我使用的是Visual C ++。其他编译器可能会稍微不同地实现__VA_ARGS__,因此您可能需要调整实现。

答案 1 :(得分:2)

接受变量参数的函数必须能够以某种方式告诉它何时到达变量参数的末尾。这可以通过解析来自固定参数的信息(例如,一个参数告诉你传递了多少变量参数,或一个格式字符串告诉你应该遵循什么参数),或者它可以是一个显式的sentinel值,例如作为空指针,在变量参数的末尾。

你似乎想要一个重大的奇迹;对不起,只有很小的奇迹。

您可以像这样设计界面:

int test1(int x, struct list *list) { ...code to handle adding x to arbitrary list... }

int test0(int x) { return test1(x, &global_struct); }

如果要使用默认列表,请调用test0();如果要指定其他列表,则调用test1()

请注意test0()非常简单,因此它是C99 inline函数定义的理想选择。

如果你使用C ++,你可以提供一个带有默认参数或重载函数的函数(两个参数列表和实现,如上所述,但名称相同)。当然,甚至比在C中还要多,在C ++中不推荐使用全局变量。

答案 2 :(得分:1)

函数必须有一些方法来知道已经给出了多少参数。你的功能没办法,所以无法正常工作。你可以创建两个函数。你可以有一个单独的“参数个数”参数。您可以包含一些其他参数,间接告诉它有多少参数(如printf使用)。但你必须以某种方式去做。