P99
|
◆ P99_CALL_VA_ARG
Assure type safety for variadic functions. Variadic functions in C have a big loophole in that they don't enforce the types for parameters that are given to the ... list. This may have severe consequences when you pass constants as arguments to such functions and the resulting type differs from what is expected. A classical example is void toto_raw(size_t len, ...);
expects the parameter toto_raw(2, NULL, malloc(23));
toto_raw(2, 0, malloc(23));
toto_raw(2, (void*)0, malloc(23));
Depending on the compiler, the first two might both result in an P99_CALL_VA_ARG allows you to "declare" the type of the ... arguments. #define toto(...) P99_CALL_VA_ARG(toto_raw, 1, void*, __VA_ARGS__)
All the following calls of toto(0);
toto(1, NULL);
toto(1, 0);
toto(1, (void*)0);
toto(2, NULL, malloc(23));
toto(2, 0, malloc(23));
toto(2, (void*)0, malloc(23));
The conversion of the arguments to type T is done with P99_RVAL. So all values passed in the variadic list must be assignment compatible with type T. This macro also allows you to declare default values for the M first arguments. We could for example do #define toto_defarg_0() 0
Then calling toto();
The convention for these symbols is that the number at the end corresponds to the position of the argument, starting from 0. This may be a macro, as above, or a function. We could have achieved the same effect by declaring inline size_t toto_defarg_0(void) { return 0; }
The arguments in the variadic list may have not only a default type but may have a default value, too. #define toto_defarg() ((void*)0)
By that toto(1,);
would expand to something equivalent to toto(1, (void*)0);
The naming convention is similar to that stated above for the numbered arguments, only that the suffix "_N" is omitted from the name of the function or macro. Definition at line 424 of file p99_defarg.h. |