ISO/IEC JTC1/SC22/WG14 N506 Proposal UK009a - Assorted changes for variable argument handling Clive D.W. Feather Summary ------- This proposal provides additional facilities to make variable arguments easier to use: a va_list copier, and "varargs safe" versions of certain types. Conformance ----------- This proposal includes new identifiers. The present proposal uses names in the reserved namespace in order to avoid affecting strictly conforming programs. If more attractive names not in the reserved namespace are used instead, some strictly conforming programs will be affected. No other aspect of the proposal affects any strictly conforming program. Discussion ---------- C89 defines certain types for which it is unspecified whether or not they are affected by the default argument promotions. Therefore it is not possible to pass values of these types to functions with variable length argument lists (other than by convolutions such as using pointers). This proposal makes the promoted types available where potentially different. Sometimes processing variable arguments would be easier if the state of processing could be copied, and then reverted to at a later point. However, there is currently no way to do this. This proposal adds such a copying mechanism. Detailed proposal ----------------- In subclause 7.8, replace: The header declares a type and defines three macros, with: The header declares several types and defines several macros, replace: The type declared is va_list which is a type suitable for holding information needed by the macros va_start, va_arg, and va_end. with: One type declared is va_list which is a type suitable for holding information needed by the macros va_start, va_arg, va_end, and __va_copy. and add at the end the new paragraph: The remaining types declared are those in the first column, each of which shall be the type resulting when the default argument promotions are applied to the type in the second column: __clock_pt clock_t __fpos_pt fpos_t __mbstate_pt mbstate_t __ptrdiff_pt ptrdiff_t __sig_atomic_pt sig_atomic_t __size_pt size_t __time_pt time_t __wchar_pt wchar_t __wctrans_pt wctrans_t __wctype_pt wctype_t __wint_pt wint_t In subclause 7.8.1, replace: It is unspecified whether va_end is a macro or an identifier declared with external linkage. If a macro definition is suppressed in order to access an actual function, or a program defines an external identifier with the name va_end, the behavior is undefined. with: It is unspecified whether va_end and __va_copy are macros or identifiers declared with external linkage. If a macro definition is suppressed in order to access an actual function, or a program defines an external identifier with the name va_end or __va_copy, the behavior is undefined. Add a new subclause 7.8.1.4: 7.8.1.4 The __va_copy macro Synopsis #include void __va_copy (va_list dest, va_list src); Description The __va_copy function or macro makes the va_list dest be a copy of the va_list src, as if the va_start macro had been applied to it followed by the same sequence of uses of the va_arg macro as had previously been used to reach the present state of src. Returns The __va_copy function or macro returns no value. Add a second example: Example The function f3 is similar, but saves the status of the variable argument list after the indicated number of arguments; after f2 has been called once with the whole list, the trailing part of the list is gathered again and passed to function f4. #include #define MAXARGS 31 void f3(int n_ptrs, int f4_after, ...) { va_list ap, ap_save; char *array[MAXARGS]; int ptr_no = 0; if (n_ptrs > MAXARGS) n_ptrs = MAXARGS; va_start(ap, n_ptrs); while (ptr_no < n_ptrs) { array[ptr_no++] = va_arg(ap, char *); if (ptr_no == f4_after) __va_copy(ap_save, ap); } va_end(ap); f2(n_ptrs, array); /* Now process the saved copy */ n_ptrs -= f4_after; ptr_no = 0; while (ptr_no < n_ptrs) array[ptr_no++] = va_arg(ap_save, char *); va_end(ap_save); f4(n_ptrs, array); }