Integer Rank in C Type Conversions
In the C programming language, the concept of integer conversion rank provides a strict, standardized hierarchy that governs how operands of differing integer types are implicitly converted during expression evaluation. Whenever an operation involves mixed types, the compiler does not perform calculations on mismatched bit-widths or incompatible signedness arbitrarily. Instead, it relies on integer rank to dictate both integer promotions—elevating smaller types to standard machine-sized integers—and the "usual arithmetic conversions," which reconcile differing types into a single common type to ensure predictable and safe computation.
Every integer type in C is assigned a specific rank according to standard language rules. The basic hierarchy of signed types, listed from highest to lowest rank, is:
long long intlong intintshort intsigned char
Unsigned integer types share the exact same rank as their
corresponding signed counterparts (for example,
unsigned int has the same rank as signed int).
The _Bool (or bool) type holds the lowest rank
of all integer types. Standard char shares the same rank as
signed char and unsigned char, regardless of
whether the implementation treats plain char as signed or
unsigned by default. Extended integer types, if provided by an
implementation, are integrated into this hierarchy based on their
precision.
Integer rank first governs the process of integer promotion, which is
applied automatically to operands in unary and binary expressions. Any
integer type with a rank strictly less than the rank of int
and unsigned int (such as char,
short, or bit-fields) is immediately promoted. If the
original type's complete value range can be represented by a standard
int, the value is converted to int; otherwise,
it is converted to unsigned int. This step eliminates
sub-int operations, standardizing the minimum working type
at the machine level.
After integer promotions are applied, the compiler uses integer rank to determine the "usual arithmetic conversions" for binary operators when the operands still differ in type. The resolution follows a deterministic set of precedence rules:
- Same Signedness: If both operands are signed or
both are unsigned, the operand with the lower conversion rank is
converted to the type of the operand with the higher rank. For example,
in an operation between
intandlong int, theintis converted tolong int. - Unsigned Rank Greater Than or Equal: If the
unsigned operand has a conversion rank greater than or equal to the rank
of the signed operand, the signed operand is converted to the type of
the unsigned operand. For instance, in an expression combining
intandunsigned int, theintis converted tounsigned int. - Signed Rank Greater With Full Representation: If
the signed operand has a greater rank than the unsigned operand, and the
signed type can represent all possible values of the unsigned type, the
unsigned operand is converted to the signed type. For example, on a
system where
longis 64-bit andunsigned intis 32-bit, theunsigned intsafely converts tolong. - Signed Rank Greater Without Full Representation: If
the signed operand has a higher rank but cannot represent all values of
the unsigned operand (such as when both types have the same width, as
often occurs with
longandunsigned inton certain platforms), both operands are converted to the unsigned counterpart of the signed type (e.g.,unsigned long).
Through these structured rules, integer rank ensures that implicit type coercion in C is consistent, preventing undefined behavior and minimizing data truncation across different hardware architectures.