不指定参数数量的可变函数

问题描述 投票:0回答:2

我正在研究C编程语言,发现非常有趣的一件事是可变参数函数的实现。我目前正在尝试打印传递给函数的每个值,但是我只得到一部分参数。

我尝试运行一些我在网上找到的示例,以求得参数的平均值以及求和算法(如下所示)。

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

int sum(int count, ...)
{
    va_list args;
    va_start(args, count);
    int total = 0;

    for (int i = 0; i < count; i++) {
        int num = va_arg(args, int);
        total += num;
        printf("Value #%d: %d\n", i, num);
    }

    va_end(args);

    return total;
}

int main()
{
    int result = sum(1, 2, 3, 4, 5);
    printf("The result is: %d\n", result);
}

上面的代码仅打印:

Value #0: 2
The result is: 2

我认为是因为for循环使用第一个参数作为索引的最大值。但是...

我的问题是,如果不需要在格式化字符串中传递要替换的参数数量,printf的工作原理是什么?是因为在后台,C运行时计算了格式化字符串中声明了多少个格式说明符?那是我的猜测。

提前感谢。

c variadic-functions
2个回答
2
投票

无法找出实际上提供了多少个参数。

printf()从格式字符串中找出来。格式字符串中的每个%运算符都对应一个参数(这是一种简化形式),它需要处理的参数数量足以填充每个参数。

所以,如果你写:

printf("%d %s\n", intvar, stringvar);

它知道必须有2个其他参数:一个用于%d,另一个用于%s

某些功能使用的另一种方法是用哨兵值指示最后一个参数。

execl("program", "arg0", "arg1", "arg2", (char *)NULL);

[execl()]处理参数,直到达到NULL值。


0
投票

如果您将可变参数函数称为:

int result = sum(5 /*count*/, 1, 2, 3, 4, 5);

通过添加首字母5(一个计数),它可以实现您期望的效果,但是为了有趣,请尝试使用更大的数字(例如6或10)进行调用,然后看看会发生什么。它们很容易出错。

对于可变参数函数,几乎唯一的好案例是针对您的应用量身定制的printf变体。我最喜欢的是die(),它采用printf样式的格式字符串(和参数),将其发送到标准错误,追加换行符,然后退出程序。

#include <stdlib.h>
#include <stdarg.h>

void die(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vprintf(stderr, format, args);
    va_end(args);
    fprintf(stderr, "\n");

    exit(EXIT_FAILURE);
}

然后将其放在头文件中以使用它:

extern void die(const char *format, ...)
   __attribute__((noexit))         // function never exits
   __attribute__((printf(1, 2)));  // looks like printf, format is arg1

现在您可以调用die("Program failed because %s", reason);,它在程序上运行时没有很多麻烦和大惊小怪。并且由于使用__attribute__,编译器(至少是GNU)知道如何验证格式字符串的参数。

© www.soinside.com 2019 - 2024. All rights reserved.