"int
type should be 4 byte on 32 bit machines and 8 byte on 64 bit machines, is that right?" No. According to the Standard, int
s must be at least 16 bits in width (§5.2.4.2.1), but there is no further stipulation.
When you pass a long long int
to printf()
it is not subject to the integer promotions (§6.3.1.1 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.
If you pass a long double
to printf()
no conversion is made (§6.5.2.2 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.
The conversion specifiers corresponding to the arguments in the printf()
statement have no bearing on these promotions and conversions, except insofar as there will be undefined behavior if the specifiers and the types of their corresponding arguments do not match.
So, the integer promotions are performed, and float
s are converted to double
s, but "No other conversions are performed implicitly" (§6.5.2.2 8).
Addressing your edit to the question: "this makes me think that not all parameters are promoted to int
." Correct. Only integer types with integer conversion rank "less than or equal to the rank of int
and unsigned int
" are subject to integer promotion. It is simpler for floating point types; float
s are promoted to double
. That is all.
It may be worth pointing out that, according to §6.2.5 10, there are three real floating point types, float
, double
, and long double
. The values which may be held by a float
are a subset of the values which may be held by a double
, which are in turn a subset of the values which may be held by a long double
. Hence, there is no possibility of promotion for long double
types.
Further, according to §6.3.1.1 1:
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.
So there is no possibility of a long long int
or long int
ever being promoted to int
or unsigned int
.
As for your final concern that promotion of a short
to an int
may, in some implementation, be impossible without losing some bits, note that §6.2.5 8 guarantees that an int
must be able to contain a short
, since the conversion rank of an int
must be greater than that of a short
:
For any two integer types with the same signedness and different
integer conversion rank (see 6.3.1.1), the range of values of the type
with smaller integer conversion rank is a subrange of the values of
the other type.