我阅读了关于va_start的手册页并获取了这个:
参数last是变量参数列表之前的最后一个参数的名称,也就是调用函数知道类型的最后一个参数。
因为可以在va_start()宏中使用此参数的地址, 不应将其声明为寄存器变量,也不应声明为函数或 数组类型。
我尝试了这段代码并且效果很好,但这让我很困惑。
#include <stdio.h>
#include <stdarg.h>
void va_func(int i[3],...);
int main()
{
int m[3] = {0,1,2};
va_func(m,4,5,5,6);
return 0;
}
void va_func(int m[5],...)// I pass a array type here before the "..."
{
int i,j;
va_list ap;
va_start(ap,m);
for(i = 0; i < 4 ;i++)
{
j = va_arg(ap,int);
printf("argv[%d] is %d\n",i,j);
}
va_end(ap);
}
然后我想阅读那些va_*
宏的代码。但我从<stdarg.h>
得不到任何结果
和<cstdarg>
。任何黑客都可以告诉我如何以及在哪里可以学习va_*
件事物?
这是我目前的问题:
我想写一个Open(const char *path,int oflag, ...);
函数。我希望它调用open
并进行一些错误测试。
int Open(const char * path,int oflag, ...)
{
int rt;
rt = open(path,oflag,...)// I don't know how to do this now.
if(rt == -1)
err_deal_func();
else
return rt;
}
答案 0 :(得分:2)
C运行时无法知道传递了多少个参数。因此,不可能轻易转发论据。大多数接受转发参数的函数都会接受va_list
对象(例如,参见vprintf
)。
您需要了解传递的参数,以便能够判断您收到了多少参数。 printf
能够通过读取格式字符串来实现,并且每次在字符串中看到占位符时,它都会读取下一个参数;但是如果你输入一个不正确的格式字符串或不正确的参数,你就会崩溃。
这也是open
的作用:
oflag
参数可能表示如果要创建文件 不存在(通过指定O_CREAT
标志)。在这种情况下,打开需要一个 第三个论点mode_t mode
;如上所述,使用模式模式创建文件 在chmod(2)中并由进程'umask value修改(参见umask(2))。
也就是说,如果oflag
不包含O_CREAT
,它不会尝试读取第三个参数。这也是你需要做的,正如你所看到的,它有点血腥。
如果您正在使用C ++(而不仅仅是普通的旧C),我建议您使用函数重载,它具有类型安全的附加好处(并且它是巨大的好处):
int Open(const char * path,int oflag)
{
int rt = open(path,oflag);
if(rt == -1)
err_deal_func();
else
return rt;
}
int Open(const char * path,int oflag,mode_t mode)
{
int rt = open(path,oflag,mode);
if(rt == -1)
err_deal_func();
else
return rt;
}
如果您确实需要在C(而不是C ++)中执行此操作,则需要使用oflag
参数来确定是否需要读取其他参数。
int Open(const char* path, int oflag, ...)
{
int rt;
if ((oflag & O_CREAT) == O_CREAT)
{
// we have O_CREAT, this means that we were passed 3 arguments
// declare argument list
va_list ap;
// create an argument list starting after the `oflag` argument
va_start(ap, oflag);
// read the next argument in `ap` as a `mode_t` variable
mode_t mode = va_arg(ap, mode_t);
// there are no more arguments to read, so clean up the list
va_end(ap);
// finally, call `open` passing that additional parameter
rt = open(path, oflag, mode);
}
else
rt = open(path, oflag);
if (rt == -1)
err_deal_func();
else
return rt;
}
答案 1 :(得分:1)
变量参数函数中...
之前的参数是特殊的;标准称它为parmN
,它用于提供有关变量参数部分的数量和可能类型的信息。
parmN
将使用 va_start
,因此无法省略:
void va_start(va_list ap, parmN);
如果是open
:
int open(const char *path, int oflag, ... );
oflag
是特殊参数,open
将检查它的值以确定它将作为变量参数部分接收的内容。
要开始一个简单的示例,您可以在C FAQ中查看this article。
答案 2 :(得分:0)
在C / C ++中不可能有一个数组类型的参数:
参数声明为''数组类型''应调整为 ''指向类型的限定指针',......(C99标准,6.7.5.3第7段)
代码中的i
和m
都有int *
类型。
在C / C ++中也不可能有函数类型的参数:
参数声明为''函数返回类型''应为 调整为''指向函数返回类型的指针'',...(C99标准, 6.7.5.3第8段)
因此,va_start
文档中关于函数参数或数组类型的陈述似乎完全没有意义。