DEV Community

Cover image for Integers and Floating-Point Numbers in C++
Tomáš Svojanovský
Tomáš Svojanovský

Posted on

Integers and Floating-Point Numbers in C++

File Extensions in C++

Before we start writing code, it is worth mentioning that C++ source files can use different file extensions.

Common C++ file extensions include:

.cc
.cpp
.cxx

Enter fullscreen mode Exit fullscreen mode

All three are valid for C++ source files.

In practice, .cpp and .cc are probably the most common ones. The .cxx extension is also valid, but you will usually see it less often.

For this example, let’s imagine we create a file called:

integers_floats.cpp

Integer Types in C++

An integer is a whole number without a fractional part.

Examples of integers are:

0
42
-10
100000
Enter fullscreen mode Exit fullscreen mode

In C++, integers can be either:

signed
unsigned
Enter fullscreen mode Exit fullscreen mode

A signed integer can store both negative and positive values.

An unsigned integer can store only zero and positive values.

For example:

-10   // signed
0     // signed or unsigned
42    // signed or unsigned
Enter fullscreen mode Exit fullscreen mode

Fixed-Width Integer Types

C++ provides a standard library header called:

#include <cstdint>

This header gives us access to fixed-width integer types.

These are useful because they allow us to specify exactly how many bits an integer should use.

For example:

std::int32_t

This means:

a signed integer with 32 bits

Here is a simple example:

#include <cstdint>

int main() {
    std::int32_t i1 = 0;
}
Enter fullscreen mode Exit fullscreen mode

The type std::int32_t stores a signed 32-bit integer.

Signed and Unsigned Integer Types

The header gives us several useful integer types.

Signed integer types:

std::int8_t
std::int16_t
std::int32_t
std::int64_t
Enter fullscreen mode Exit fullscreen mode

Unsigned integer types:

std::uint8_t
std::uint16_t
std::uint32_t
std::uint64_t
Enter fullscreen mode Exit fullscreen mode

The number in the type name tells us how many bits the type uses.

For example:

std::int8_t   // signed 8-bit integer
std::int16_t  // signed 16-bit integer
std::int32_t  // signed 32-bit integer
std::int64_t  // signed 64-bit integer
Enter fullscreen mode Exit fullscreen mode

And for unsigned integers:

std::uint8_t   // unsigned 8-bit integer
std::uint16_t  // unsigned 16-bit integer
std::uint32_t  // unsigned 32-bit integer
std::uint64_t  // unsigned 64-bit integer
Enter fullscreen mode Exit fullscreen mode

A larger number of bits means the type can store a larger range of values.

For example, a 64-bit integer can store much larger values than an 8-bit integer.

Example: Using Fixed-Width Integer Types

Here is an example using several integer types:

#include <cstdint>

int main() {
    std::int8_t i8 = 0;
    std::int16_t i16 = 0;
    std::int32_t i32 = 0;
    std::int64_t i64 = 0;

    std::uint8_t u8 = 0;
    std::uint16_t u16 = 0;
    std::uint32_t u32 = 0;
    std::uint64_t u64 = 0;
}
Enter fullscreen mode Exit fullscreen mode

This gives us a clear way to define the size and signedness of our integer variables.

Integer Literals and the U Suffix

When writing unsigned integer values, you can add a U suffix to the number.

For example:

std::uint32_t value = 42U;

The U tells the compiler that the literal should be treated as unsigned.

You can use either lowercase or uppercase:

42u
42U
Enter fullscreen mode Exit fullscreen mode

Both are valid.

Personally, I prefer the uppercase version because it is easier to see.

For larger unsigned values, you may also see suffixes like:

42ULL

This means an unsigned long long literal, which is usually used for larger integer values.

For now, the important thing to remember is this:

U

is commonly used to indicate that a number is unsigned.

Floating-Point Types in C++
Enter fullscreen mode Exit fullscreen mode

Integers are useful for whole numbers.

But what if we need decimal values?

For example:

3.14
12.5
0.001
Enter fullscreen mode Exit fullscreen mode

For these values, C++ provides floating-point types.

The two most common floating-point types are:

float
double
Enter fullscreen mode Exit fullscreen mode

A float is usually a 32-bit floating-point number.

A double is usually a 64-bit floating-point number.

Example:

int main() {
    float f1 = 12.0F;
    double d1 = 12.0;
}
Enter fullscreen mode Exit fullscreen mode

Why Use F with Float Literals?

In C++, a decimal literal such as this:

12.0

is interpreted as a double by default.

So if you write:

float f1 = 12.0;

the value on the right side is first treated as a double, and then it is stored into a float.

To make it clear that the literal itself should be a float, you can add the F suffix:

float f1 = 12.0F;

You can also write:

float f1 = 12.0f;

Both lowercase f and uppercase F are valid.

Again, I prefer uppercase because it is easier to read.

float and double Compared to Other Languages

Some modern languages use names such as:

float32
float64
Enter fullscreen mode Exit fullscreen mode

For example, Rust has:

f32
f64
Enter fullscreen mode Exit fullscreen mode

C++ does not use these names directly for built-in floating-point types.

Instead, C++ uses:

float   // usually 32-bit
double  // usually 64-bit
Enter fullscreen mode Exit fullscreen mode

You can define your own aliases if you want names like float32 or float64, but that is a topic for another article.

Boolean Values

C++ also has a boolean type:

bool

A boolean can store one of two values:

true
false
Enter fullscreen mode Exit fullscreen mode

Example:

int main() {
    bool is_active = true;
    bool is_finished = false;
}
Enter fullscreen mode Exit fullscreen mode

A boolean is not usually considered a numeric type in the same way as integers and floats, but it is still one of the fundamental primitive types in C++.

Characters in C++

C++ also has a character type:

char

A char stores a single character.

Example:

int main() {
    char c1 = 'A';
    char c2 = 'z';
}
Enter fullscreen mode Exit fullscreen mode

Notice the single quotation marks:

'A'
'z'
Enter fullscreen mode Exit fullscreen mode

Single quotation marks are used for single characters.

Double quotation marks are used for strings:

'A'    // character
"A"    // string
Enter fullscreen mode Exit fullscreen mode

This distinction is very important in C++.

Characters Are Integers Under the Hood

Although we use char for characters, under the hood characters are represented as integer values.

For example, the character:

'A'

is mapped to a numeric value using a character encoding table such as ASCII.

In ASCII, characters like A, B, C, a, b, and c all correspond to numeric values.

That means char is closely related to integer types internally.

However, when storing single characters, we normally use:

char

instead of:

std::int8_t
std::uint8_t
Enter fullscreen mode Exit fullscreen mode

Even though they may be similar in size, char better communicates the intention: we are storing a character, not just a small number.

Why Not Just Use int?

In many C++ tutorials, you will often see code like this:

int value = 42;

This works, and int is still very commonly used.

However, the exact size of int can depend on the platform and compiler.

For example, on one system an int might be 32 bits. On another system, such as some embedded platforms, it might be 16 bits.

That means when you write:

int value = 42;

you do not always know exactly how many bits the type has.

For modern C++ code, especially when the exact size matters, fixed-width integer types from are often a better choice.

For example:

std::int32_t value = 42;

This makes the intention much clearer.

You are saying:

I want a signed integer with exactly 32 bits.

Summary

C++ gives us several ways to store numeric values.

For integers, we can use fixed-width types from the header:

std::int8_t
std::int16_t
std::int32_t
std::int64_t
std::uint8_t
std::uint16_t
std::uint32_t
std::uint64_t
Enter fullscreen mode Exit fullscreen mode

For decimal values, we usually use:

float
double
Enter fullscreen mode Exit fullscreen mode

For boolean values, we use:

bool

And for single characters, we use:

char

The key idea is that different types have different sizes, ranges, and meanings.

Top comments (0)