-
Notifications
You must be signed in to change notification settings - Fork 2
/
stdarg.3
123 lines (121 loc) · 3 KB
/
stdarg.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
.\" @(#)varargs.3 6.3 (Berkeley) 5/15/86
.\"
.TH STDARG 3 "May 15, 1986"
.AT 3
.SH NAME
stdarg \- variable argument list
.SH SYNOPSIS
.nf
.ft B
#include <stdarg.h>
void va_start(va_list \fIap\fP, \fIargtypeN\fP \fIparmN\fP)
\fItype\fP va_arg(va_list \fIap\fP, \fItype\fP)
void va_end(va_list \fIap\fP)
.ft R
.fi
.SH DESCRIPTION
This set of macros provides a means of writing portable procedures that
accept variable argument lists.
Routines having variable argument lists (such as
.BR printf (3))
that do not use
.B stdarg
are inherently nonportable, since different
machines use different argument passing conventions.
.PP
A function that accepts a variable argument list is declared with "..." at
the end of its parameter list. It must have at least one normal argument
before the "...". For example:
.PP
.RS
.nf
int printf(const char *format, ...) { /* code */ }
int fprintf(FILE *stream, const char *format, ...) { /* code */ }
.fi
.RE
.PP
.B va_list
is a type which is used for the variable
.I ap
within the body of a variable argument function which is used to traverse
the list.
.PP
.B va_start\c
.RI ( ap ,
.IR parmN )
is called to initialize
.I ap
to the beginning of the list. The last true parameter of the function,
.IR parmN ,
must be supplied to allow
.B va_start
to compute the address of the first variable parameter.
.PP
.B va_arg\c
.RI ( ap ,
.IR type )
will return the next argument in the list pointed to by
.IR ap .
.I Type
is the type to which the expected argument will be converted
when passed as an argument.
.PP
Different types can be mixed, but it is up
to the routine to know what type of argument is
expected, since it cannot be determined at runtime.
.PP
.B va_end\c
.RI ( ap )
must be used to finish up.
.PP
Multiple traversals, each bracketed by
.B va_start
\&...
.B va_end,
are possible.
.SH EXAMPLE
.nf
.ta +4n +4n +4n +4n
\fB#include\fP <stdarg.h>
.sp 0.4
execl(\fBconst char\fP *path, \fB...\fP)
{
\fBva_list\fP ap;
\fBchar\fP *args[100];
\fBint\fP argno = 0;
\fBva_start\fP(ap, path);
\fBwhile\fP ((args[argno++] = \fBva_arg\fP(ap, \fBchar\fP *)) != NULL) {}
\fBva_end\fP(ap);
\fBreturn\fP execv(path, args);
}
.DT
.fi
.SH NOTES
It is up to the calling routine to determine how many arguments
there are, since it is not possible to determine this from the
stack frame. For example,
.B execl
passes a null pointer to signal the end of the list.
.B Printf
can tell how many arguments are supposed to be there by the format.
.PP
The macros
.B va_start
and
.B va_end
may be arbitrarily complex;
for example,
.B va_start
might contain an opening brace,
which is closed by a matching brace in
.BR va_end .
Thus, they should only be used where they could
be placed within a single complex statement.
.SH BUGS
It is impossible to properly show the macros as C declarations as is
done in the synopsis. They can never be coded as C functions, because
all three macros use their arguments by address, and the
.I type
field is certainly impossible.
Just look at them as being part of the C language, like
.BR sizeof .