According to the C standard (6.5.2.2 paragraph 6)
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined. If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases:
- one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;
- both types are pointers to qualified or unqualified versions of a character type or void.
Thus, in general, there is nothing wrong with passing an int to a variadic function that expects an unsigned int (or vice versa) as long as the value passed fits in both types. However, the specification for printf reads (7.19.6.1 paragraph 9):
If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
No exception is made for signed/unsigned mismatch.
Does this mean that printf("%x", 1) invokes undefined behavior?
printf("%d",(char)1);. The description ofprintfdoesn't say that it's the argument after integer promotions which must be the correct type, it says the argument itself must be. Should we conclude that it's an exception to that part of 6.5.2.2/6 as well?printfif it hasn't been prototyped, and your quote concerns calls made where there is no prototype. The same argument promotions are applied to the arguments of varargs, though, according to 6.5.2.2/7, although that doesn't say anything about signed/unsigned compatibility. So maybe you're absolutely right, and signed/unsigned compatibility is only stated to apply to calls made with no prototype, not to varargs calls in general, let aloneprintfin particular.,...prototype, the only part of 6.5.2.2/6 that is relevant is the description of default argument promotions. The mismatched arguments exceptions are not applicable. (In any case, the function must be defined with a matching prototype and the...parameters don't have a known type.) The corresponding requirements for accessing vargs are in 7.15.1.1 which describes the use of theva_argmacro. Here you are allowed to useva_argto access (e.g.) anintas anunsigned intproviding the value is in the correct range.