7.16.1.1 2 describes va_arg
as following (emphasis mine):
If there is no actual next argument, or if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:
- one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;
- one type is pointer to void and the other is a pointer to a character type.
Now to my understanding and it seems that 6.5.2.2 (function calls) does not contradict me, though I might be wrong, the default promotions are:
char
to eitherint
orunsigned
(implementation specified)signed char
toint
unsigned char
tounsigned
short
toint
unsigned short
tounsigned
float
todouble
This is all fine and dandy when you know the exact underlying types passed to the va_list
(except for char
, which AFAIK is impossible to retrieve portably because its signedness is implementation specified).
It gets more complicated when you're expecting types from <stdint.h>
to be passed to your va_list
.
int8_t
andint16_t
, deducting through logical limit observations, are guaranteed to be promoted or already be of typeint
. However it's very dubious to rely on my original "logical" limit observations, so I'm seeking your (and the standard's) confirmation on this deduction (I may be missing some corner cases I'm not even aware of).- the same holds for
uint8_t
anduint16_t
, except the underlying type isunsigned
int32_t
may or may not be promoted toint
. It may be larger than , smaller than or exactly the same asint
. Same holds foruint32_t
but forunsigned
. How to portably retrieveint32_t
anduint32_t
passed tova_list
? In other words, how to determine ifint32_t
(uint32_t
) has been promoted toint
(unsigned
)? In yet other words, how to determine whether I should useva_arg(va, int)
orva_arg(va, int32_t)
to retrieveint32_t
passed to the variadic function without invoking undefined behaviour on any platform?- I believe the same questions are valid for
int64_t
anduint64_t
.
This is a theoretical (standard-only concerned) question, with a presumption that all exact-width types in <stdint.h>
are present. I'm not interested in "what's true in practice" type of answers, because I believe I already know them.
EDIT
One idea that I have in mind is to use _Generic
to determine the underlying type of int32_t
. I'm not sure how exactly would you use it though. I'm looking for better (easier) solutions.