What Are Floating-Point and Integral Promotions?

A numeric promotion is an implicit conversion of a narrow numeric type, such as char or short, to a wider one that the processor handles efficiently, which in practice means int or double. Every numeric promotion is safe, because the wider type can represent every value the narrower one could hold.

Promotions exist for two reasons that have nothing to do with each other: one about hardware, one about how many functions you have to write.

The Hardware Reason

C++ guarantees a minimum size for each fundamental type, but the actual size depends on the compiler and the architecture. That flexibility is deliberate: it lets int and double match whatever the processor works with most naturally. A 32-bit machine typically handles 32 bits at a time, so a 32-bit int is the efficient choice there.

Reminder
The number of bits a type occupies is its width. A wider type uses more bits, a narrower type fewer.

Ask that same processor to work on an 8-bit or 16-bit value and things get worse rather than better. Some CPUs can manipulate narrow values directly but more slowly than full-width ones. Others cannot operate on them at all, and the compiler has to generate extra instructions to fake it.

Since C++ aims to be both portable and fast, the language cannot assume any particular CPU is good at handling values narrower than its natural size. Promotions are the answer: widen the value to something the hardware likes, then compute.

The Redundancy Reason

Consider a function that prints an int:

void displayInt(int value)
{
    std::cout << value << '\n';
}

Without promotions, printing a short would need its own function. So would char, and then signed char, unsigned char, unsigned short, wchar_t, char8_t, char16_t, and char32_t. That is a lot of identical functions differing only in a parameter type.

Promotions collapse the whole set. Write the function once taking int or double, and any argument that promotes to that type can be passed to it.

Value-Preserving

A value-preserving conversion, also called a safe conversion, is one where every possible source value maps to an equal value in the destination type. All numeric promotions are value-preserving, which is why the compiler applies them silently and never warns.

Floating-Point Promotions

This category has exactly one rule: a float can be converted to a double.

#include <iostream>

void displayDouble(double value)
{
    std::cout << value << '\n';
}

int main()
{
    displayDouble(19.25);
    displayDouble(7.5f);

    return 0;
}

Output:

19.25
7.5

The first call needs no conversion. In the second, the float literal 7.5f is promoted to double so it matches the parameter.

Integral Promotions

This category has more rules:

Source type Promotes to
signed char, signed short int
unsigned char, char8_t, unsigned short int if int can represent the whole range, otherwise unsigned int
char Follows signed char or unsigned char, depending on whether plain char is signed on the platform
bool int, with false becoming 0 and true becoming 1

On any typical modern setup, with 8-bit bytes and an int of at least 4 bytes, all of that reduces to a single sentence: bool, char, signed char, unsigned char, signed short, and unsigned short all become int.

#include <iostream>

void displayInt(int value)
{
    std::cout << value << '\n';
}

int main()
{
    displayInt(2);

    short quantity{ 3 };
    displayInt(quantity);

    displayInt('a');
    displayInt(true);

    return 0;
}

Output:

2
3
97
1

'a' prints as 97 because promoting a char to int yields its numeric value, and true prints as 1.

Two details are easy to miss. On an unusual architecture, such as one with 2-byte int, some unsigned types promote to unsigned int rather than int. And a narrow unsigned type can promote to a wider signed type, so while a promotion always preserves the value, it does not necessarily preserve the signedness.

For advanced readers
A few further integral promotion rules exist for less common cases. The C++ reference documentation lists them in full.

Widening Is Not the Same as Promotion

Not every conversion to a wider type is a promotion. char to short, and int to long, both widen, yet neither is a numeric promotion. They are numeric conversions, the subject of the next lesson.

The reason is purpose rather than size. Promotion exists to get values into the type the processor handles best, and short and long are not that type. Widening to them serves some other goal.

The distinction is mostly academic, with one practical exception: when the compiler is choosing between overloads, it prefers a promotion to a conversion. That preference decides real cases, as you will see when the course reaches overload resolution.

Summary

Numeric promotion: an implicit conversion of a narrow numeric type to a wider one the processor handles efficiently, typically int or double.

Why they exist: processors are often slower with values narrower than their natural width, or cannot handle them directly at all, and promotions let one function taking int or double serve arguments of many types instead of needing one overload per type.

Value-preserving: every promotion maps each source value to an equal destination value, so the compiler performs them silently and without warnings.

Floating-point promotion: float to double.

Integral promotion: bool, char, signed char, unsigned char, signed short, and unsigned short to int on typical platforms, or to unsigned int where int cannot cover the range. true becomes 1 and false becomes 0.

Signedness is not guaranteed: a narrow unsigned type may promote to a wider signed type. The value survives, the signedness need not.

Widening is not automatically promotion: char to short and int to long are numeric conversions, not promotions, and the compiler prefers promotions during overload resolution.