C++
In C++ 2011 (ISO/IEC 14882:2011), the relevant parts seem to be:
§5.2.2 Function Call [expr.call]
¶6 A function can be declared to accept fewer arguments (by declaring default arguments (8.3.6)) or more
arguments (by using the ellipsis, ..., or a function parameter pack (8.3.5)) than the number of parameters
in the function definition (8.4). [Note: this implies that, except where the ellipsis (...) or a function
parameter pack is used, a parameter is available for each argument. —end note]
¶7 When there is no parameter for a given argument, the argument is passed in such a way that the receiving
function can obtain the value of the argument by invoking va_arg (18.10). [Note: This paragraph does not
apply to arguments passed to a function parameter pack. Function parameter packs are expanded during
template instantiation (14.5.3), thus each such argument has a corresponding parameter when a function
template specialization is actually called. —end note] The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and
function-to-pointer (4.3) standard conversions are performed on the argument expression. An argument that
has (possibly cv-qualified) type std::nullptr_t is converted to type void* (4.10). After these conversions,
if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the
program is ill-formed. Passing a potentially-evaluated argument of class type (Clause 9) having a nontrivial
copy constructor, a non-trivial move contructor, or a non-trivial destructor, with no corresponding
parameter, is conditionally-supported with implementation-defined semantics.
If the argument has integral
or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject
to the floating point promotion (4.6), the value of the argument is converted to the promoted type before
the call. These promotions are referred to as the default argument promotions.
I've separated the last two sentences to give them emphasis. They're a continuous part of paragraph 7 in the standard.
§4.5 Integral promotions [conv.prom]
¶1 A prvalue of an integer type other than bool
, char16_t
, char32_t
, or wchar_t
whose integer conversion
rank (4.13) is less than the rank of int
can be converted to a prvalue of type int
if int
can represent all
the values of the source type; otherwise, the source prvalue can be converted to a prvalue of type unsigned
int
.
¶2 A prvalue of type char16_t
, char32_t
, or wchar_t
(3.9.1) can be converted to a prvalue of the first of
the following types that can represent all the values of its underlying type: int
, unsigned int
, long int
,
unsigned long int
, long long int
, or unsigned long long int
. If none of the types in that list can
represent all the values of its underlying type, a prvalue of type char16_t
, char32_t
, or wchar_t
can be
converted to a prvalue of its underlying type.
Etc.
C
C has two contexts where arguments are default promoted. One is when there is no prototype in scope for a function (first covered by another answer), and the second when there is a prototype with ellipsis. C++ does not allow the first case at all, of course. These quotes are from the same sections of the standard as chosen by another answer, but the snippets here are somewhat longer. They were found by independent analysis of the standard, and it was only when cross-checking that I noticed that the sections are the same.
In C 2011 (ISO/IEC 9899:2011), the relevant parts seem to be:
§6.5.2.2 Function calls
¶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.
¶7 If the expression that denotes the called function has a type that does include a prototype,
the arguments are implicitly converted, as if by assignment, to the types of the
corresponding parameters, taking the type of each parameter to be the unqualified version
of its declared type. The ellipsis notation in a function prototype declarator causes
argument type conversion to stop after the last declared parameter. The default argument
promotions are performed on trailing arguments.
The 'integer promotions' are defined in §6.3.1.1:
§6.3.1 Arithmetic operands
§6.3.1.1 Boolean, characters, and integers
¶1 Every integer type has an integer conversion rank defined as follows:
— No two signed integer types shall have the same rank, even if they hav e the same
representation.
— The rank of a signed integer type shall be greater than the rank of any signed integer
type with less precision.
— The rank of long long int shall be greater than the rank of long int, which
shall be greater than the rank of int, which shall be greater than the rank of short
int, which shall be greater than the rank of signed char.
— The rank of any unsigned integer type shall equal the rank of the corresponding
signed integer type, if any.
— The rank of any standard integer type shall be greater than the rank of any extended
integer type with the same width.
— The rank of char shall equal the rank of signed char and unsigned char.
— The rank of _Bool shall be less than the rank of all other standard integer types.
— The rank of any enumerated type shall equal the rank of the compatible integer type
(see 6.7.2.2).
— The rank of any extended signed integer type relative to another extended signed
integer type with the same precision is implementation-defined, but still subject to the
other rules for determining the integer conversion rank.
— For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has
greater rank than T3, then T1 has greater rank than T3.
¶2 The following may be used in an expression wherever an int
or unsigned int
may
be used:
— An object or expression with an integer type (other than int
or unsigned int
)
whose integer conversion rank is less than or equal to the rank of int
and
unsigned int
.
— A bit-field of type _Bool
, int
, signed int
, or unsigned int
.
If an int
can represent all values of the original type (as restricted by the width, for a
bit-field), the value is converted to an int
; otherwise, it is converted to an unsigned
int
. These are called the integer promotions.58) All other types are unchanged by the
integer promotions.
58) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain
argument expressions, to the operands of the unary +, -, and ~ operators, and to both operands of the
shift operators, as specified by their respective subclauses.
I note that at one time, the question listed the function void f(...);
, which is a C++ function and not a C function; C does not allow the ellipsis to appear as the only argument to the function. The question has since been updated to void f(int, ...);
which is valid in both C and C++.