Integer Promotions vs Arithmetic Conversions in C++
In C++, implicit type conversions occur automatically during
expression evaluation to maintain consistency and match underlying
processor architectures. Although standard integer promotions and
general arithmetic conversions (formally referred to as "usual
arithmetic conversions") are closely related, they represent distinct
stages of this process. Standard integer promotions elevate small
integral types to int or unsigned int to
prevent value truncation and optimize hardware registers. In contrast,
usual arithmetic conversions apply to binary expressions containing
mixed arithmetic types, determining a single common type so the
operation can be evaluated safely.
Standard Integer Promotions
Standard integer promotions apply to small integer types, unscoped
enumerations, and bit-fields. Types with an integer conversion rank
lower than that of signed int—such as bool,
char, signed char, unsigned char,
short, and unsigned short—are automatically
promoted before an operation occurs.
The promotion rules are straightforward:
- If
intcan represent all values of the original type, the value is converted toint. - If
intcannot represent all values (which can occur withunsigned shorton systems wheresizeof(short) == sizeof(int)), the value is converted tounsigned int.
Integer promotions can occur on single operands (unary operations
such as +, -, or ~) or as an
initial phase of a binary operation. For example, adding two
char variables causes both to be promoted to
int before the addition takes place:
char a = 10;
char b = 20;
auto result = a + b; // Type of 'result' is int, not charGeneral (Usual) Arithmetic Conversions
Usual arithmetic conversions are a structured set of rules applied to
the operands of most binary operators (such as +,
-, *, /, <, and
==) when the operands have different arithmetic types. The
objective is to find a common type that both operands can be safely
converted to before the operation executes.
The conversion follows a strict hierarchy:
- Floating-Point Handling: If either operand is a
floating-point type, the operand with the lower rank is converted to the
type of the operand with the higher rank (e.g.,
floattodouble, ordoubletolong double). - Integral Promotion Step: If neither operand is a floating-point type, standard integer promotions are first applied to both operands.
- Integral Type Balancing: If the types still differ
after promotion, they are adjusted using rank-based rules:
- If both operands are signed or both are unsigned, the operand with
the lower conversion rank is converted to the type of the higher rank
(e.g.,
intbecomeslong). - If the operand with the unsigned type has a rank greater than or equal to the signed operand, the signed operand is converted to the unsigned type.
- If the signed type can represent all values of the unsigned type, the unsigned operand is converted to the signed type. Otherwise, both operands are converted to the unsigned version of the signed operand's type.
- If both operands are signed or both are unsigned, the operand with
the lower conversion rank is converted to the type of the higher rank
(e.g.,
For example, mixing a signed integer with an unsigned integer:
int a = -5;
unsigned int b = 10;
auto result = a + b; // 'a' is converted to unsigned int; result is unsigned intKey Differences
- Scope and Applicability: Integer promotions apply to single operands of small integral types, including in unary operations and shift counts. Arithmetic conversions apply strictly to binary expressions with two operands.
- Pipeline Hierarchy: Integer promotion is a subset and prerequisite of arithmetic conversions. When two integers are operated on, the compiler first promotes any small integers before executing the broader rules of usual arithmetic conversions.
- Target Type: Integer promotions exclusively convert
to either
intorunsigned int. Usual arithmetic conversions can yield any arithmetic type, includinglong long,float,double, orunsigned long, depending on the highest-ranking operand involved.