i read man page va_start , this:
the argument last name of last argument before variable argument list, is, last argument of calling function knows type.
because address of argument may used in va_start() macro, it should not declared register variable, or function or array type.
i tried code , works well, makes me confused.
#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],...)// pass array type here before "..." { int i,j; va_list ap; va_start(ap,m); for(i = 0; < 4 ;i++) { j = va_arg(ap,int); printf("argv[%d] %d\n",i,j); } va_end(ap); }
then want read code of
va_*
macros. nothing<stdarg.h>
,<cstdarg>
. can hacker tell me how , can learnva_*
things?
here current problem:
i want write open(const char *path,int oflag, ...);
function. hope call open
, error test.
int open(const char * path,int oflag, ...) { int rt; rt = open(path,oflag,...)// don't know how now. if(rt == -1) err_deal_func(); else return rt; }
the c runtime provides no way know how many arguments passed. therefore, it's not possible forward arguments easily. functions accept forwarded arguments accept va_list
object (see vprintf
instance).
you need understand parameters passed able tell how many received. printf
able reading format string, , each time sees placeholder in string, reads next parameter; if feed incorrect format string or incorrect parameters, you're going crash.
this open
does, too:
the
oflag
argument may indicate file created if not exist (by specifyingo_creat
flag). in case, open requires third argumentmode_t mode
; file created mode mode described in chmod(2) , modified process' umask value (see umask(2)).
that is, not seek read third parameter if oflag
doesn't include o_creat
. need well, , can see, it's gory.
if you're doing c++ (and not plain old c), suggest use function overloads, has added benefit of being type-safe (and it's huge benefit):
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; }
if need in c (and not c++), need use oflag
parameter determine if need read additional parameter.
int open(const char* path, int oflag, ...) { int rt; if ((oflag & o_creat) == o_creat) { // have o_creat, means passed 3 arguments // declare argument list va_list ap; // create argument list starting after `oflag` argument va_start(ap, oflag); // read next argument in `ap` `mode_t` variable mode_t mode = va_arg(ap, mode_t); // there no more arguments read, clean list va_end(ap); // finally, call `open` passing additional parameter rt = open(path, oflag, mode); } else rt = open(path, oflag); if (rt == -1) err_deal_func(); else return rt; }