我正在阅读如何将可选参数传递给函数。但我无法理解这些。当我看到例子时,它们令人困惑,有点复杂。所以我刚开始用一个非常简单的程序来完成我迄今所理解的内容。
以下程序只打印变量。
void print(int x, ...)
{
va_list ap;
int i = 4; // I know I'm passing only 4 opt variables.
int num;
va_start(ap, x);
while(i--) { // How to know how many variables came in real time?
num = va_arg(ap, int);
printf("%d\n", num);
}
va_end(ap);
return;
}
int main()
{
print(1,2,3,4,5);
return 0;
}
我不知道上面的程序是对还是不对。但它正在发挥作用。当我将i
值更改为5
打印垃圾时。如何知道我得到了多少论点(如argc
中的main
)?
答案 0 :(得分:8)
无法知道从变量参数函数中传递了多少参数,这就是为什么诸如printf
之类的函数使用特殊格式字符串来告诉函数预期有多少参数
另一种方式当然是传递"额外"参数作为第一个参数,如
print(4, 1, 2, 3, 4);
或者有一个特殊的值不能作为最后一个参数列在列表中,比如
print(1, 2, 3, 4, -1);
您还必须注意,传递给函数的最后一个非-a参数(在您的情况下名为 num
的参数)不包含在va_list
中,因此在使用4
显示的代码作为硬编码参数的情况,当<{1}}参数传递1
然后传递三个num
时,仍然打印垃圾{1}}参数。
还要小心,因为你使用 va_list
作为参数和局部变量名。
答案 1 :(得分:7)
您可以查看NARGS macro
改编自您的代码:
#include <stdio.h>
#include <stdarg.h>
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define print(...) fnprint(NARGS(__VA_ARGS__), __VA_ARGS__)
void fnprint(int n, ...)
{
va_list ap;
int num;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
printf("%d\n", num);
}
va_end(ap);
return;
}
int main(void)
{
print(1, 2, 3, 4, 5);
return 0;
}
修改强> 如果要对宏和函数使用相同的名称,请使用()停止预处理器扩展函数定义:
#define print(...) print(NARGS(__VA_ARGS__), __VA_ARGS__)
void (print)(int n, ...) /* Note () around the function name */
{
...
编辑2:使用复合文字(std 99)和sizeof
的另一种(丑陋)方法(但不限制args数量):
#include <stdio.h>
#include <stdarg.h>
#define print(...) print(sizeof((int []) {__VA_ARGS__}) / sizeof(int), __VA_ARGS__)
void (print)(int n, ...)
{
va_list ap;
int num;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
printf("%d\n", num);
}
va_end(ap);
return;
}
int main(void)
{
print(1, 2, 3, 4, 5);
return 0;
}
print
扩展为:
print(sizeof((int []) {1, 2, 3, 4, 5}) / sizeof(int), 1, 2, 3, 4, 5);
但print(1, 2, 3, a_var++, 4, 5);
或print(1, 2, some_func_returning_int(), 4, 5);
等结构会对a_var++
和some_func_returning_int()
进行两次评估,这是个大问题。
答案 2 :(得分:0)
int和字符串的另一种丑陋方式:
#include <stdio.h>
#include <stdarg.h>
#define print(...) fnprint("{" # __VA_ARGS__ )
fnprint(char *b) {
int count = 0, i;
if (b[1] != '\0') {
for (i =2; b[i]; i++) {
if (b[i] == ',')
count++;
}
count++;
}
printf("\ncount is %i\n", count);
}
int main(void)
{
print();
print("1", "2");
print(1, 2, 3, 4, 5);
return 0;
}