Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Literals
Write numeric, string, and character literals with proper suffixes and formatting.
Literals
Literals are fixed values written directly in your code. When you type a number, character, or text string into your program, you're using a literal.
int totalScore { 100 }; // 100 is an integer literal
bool isGameActive { true }; // true is a boolean literal
double temperature { 98.6 }; // 98.6 is a double literal
std::cout << "Welcome Player!"; // "Welcome Player!" is a C-style string literal
Literals are also known as literal constants because their values cannot change. The number 100 always represents one hundred, regardless of where it appears in your code.
Understanding literal types
Every literal in C++ has a specific type, determined automatically by the compiler based on how the literal is written.
By default, the compiler assigns types as follows:
| Literal value | Examples | Default type | Notes |
|---|---|---|---|
| integer value | 100, 0, -42 | int | |
| boolean value | true, false | bool | |
| floating point value | 98.6, 0.0, 2.5 | double (not float!) | |
| character | 'x', '\t' | char | |
| C-style string | "Welcome Player!" | const char[17] | see C-style string literals section |
Changing literal types with suffixes
Sometimes you need a literal to have a different type than the default. You can accomplish this by adding a suffix to the literal.
Here are the most commonly used suffixes:
| Data type | Suffix | Meaning |
|---|---|---|
| integral | u or U | unsigned int |
| integral | l or L | long |
| integral | ul, uL, Ul, UL, lu, lU, Lu, LU | unsigned long |
| integral | ll or LL | long long |
| integral | ull, uLL, Ull, ULL, llu, llU, LLu, LLU | unsigned long long |
| integral | z or Z | The signed version of std::size_t (C++23) |
| integral | uz, uZ, Uz, UZ, zu, zU, Zu, ZU | std::size_t (C++23) |
| floating point | f or F | float |
| floating point | l or L | long double |
| string | s | std::string |
| string | sv | std::string_view |
In most situations, suffixes aren't required (with the notable exception of f for floats).
Related content: The s and sv suffixes need an extra line of code to work. We'll explore these in the Introduction to std::string and Introduction to std::string_view lessons.
Suffix case sensitivity
Most suffixes work in either uppercase or lowercase, with these exceptions:
sandsvmust be lowercase- When using double
lorL, both characters must have matching case (lLandLlare invalid)
Since lowercase L can look like the digit 1 in many fonts, many programmers prefer uppercase L.
Prefer uppercase L suffix over lowercase l.
Integer literals in action
Here's how to use suffixes with integer literals:
#include <iostream>
int main()
{
std::cout << 42 << '\n'; // 42 (no suffix) is type int (by default)
std::cout << 42L << '\n'; // 42L is type long
std::cout << 42u << '\n'; // 42u is type unsigned int
return 0;
}
Usually, plain int literals work fine even when initializing non-int types:
int main()
{
int level { 10 }; // ok: types match
unsigned int health { 100 }; // ok: compiler converts int 100 to unsigned int 100
long experience { 5000 }; // ok: compiler converts int 5000 to long 5000
return 0;
}
The compiler automatically converts the int literal to match the target variable's type.
Floating point literals
By default, floating point literals are type double. To create float literals, add the f (or F) suffix:
#include <iostream>
int main()
{
std::cout << 3.14 << '\n'; // 3.14 (no suffix) is type double (by default)
std::cout << 3.14f << '\n'; // 3.14f is type float
return 0;
}
Many beginners get confused by this compiler warning:
float pi { 3.14 }; // warning: 3.14 is a double literal, not a float literal
The literal 3.14 without a suffix is type double, not float. The compiler doesn't consider what you're doing with the literal when determining its type. Since double doesn't match float, the value must be converted, potentially losing precision. Hence the warning.
Fix this in one of two ways:
float pi { 3.14f }; // use 'f' suffix so literal matches variable type
double pi { 3.14 }; // change variable to double to match literal type
Scientific notation for floating point literals
Floating point literals can be written in two ways:
- Standard notation uses a decimal point:
double pi { 3.14159 }; // standard notation
double temperature { -40.5 }; // can be negative
double zero { 0.0 }; // prefer 0.0 over 0. for clarity
- Scientific notation uses
eto represent the exponent:
double earthMass { 5.97e24 }; // 5.97 x 10^24
double electronCharge { -1.6e-19 }; // -1.6 x 10^-19
Working with string literals
In programming, a string is a sequence of characters representing text, like player names, messages, or commands.
Here's a basic C++ program using a string literal:
#include <iostream>
int main()
{
std::cout << "Welcome Player!";
return 0;
}
"Welcome Player!" is a string literal. String literals use double quotes (unlike character literals which use single quotes).
C++ doesn't include strings as a fundamental type. Instead, it inherited C strings (or C-style strings) from the C language, which are complex and difficult to work with.
Two important facts about C-style string literals:
- All C-style string literals have an implicit null terminator. The string
"hello"actually has six characters:'h','e','l','l','o', and'\0'(ASCII code 0). This trailing'\0'character is the null terminator, marking where the string ends. Strings ending with a null terminator are called null-terminated strings.
For advanced readers: This explains why "Welcome Player!" has type const char[17] rather than const char[16] - the hidden null terminator counts as a character.
- Unlike most literals (which are values), C-style string literals are const objects created when the program starts and guaranteed to exist throughout program execution. In contrast,
std::stringandstd::string_viewliterals create temporary objects that must be used immediately before they're destroyed.
Avoiding magic numbers
A magic number is a literal with unclear meaning or one that might need changing later.
Consider these examples:
const int maxPlayers { numberOfTeams * 5 };
setLimit(5);
What does 5 mean? In the first line, you might guess it's players per team, but it's not obvious. In the second line, the meaning is completely unclear.
Magic numbers create problems when values need updating. If teams grow from 5 to 6 players, which 5s should change? You'd need to examine every occurrence of 5 in your code to determine if it relates to team size. This is time-consuming and error-prone.
Use symbolic constants instead:
const int playersPerTeam { 5 };
const int maxPlayers { numberOfTeams * playersPerTeam }; // meaning is now clear
const int maxUsernameLength { 20 };
setLimit(maxUsernameLength); // clearly different from playersPerTeam
Now the context is clear, and you only need to update values in one place.
Note that magic numbers aren't always numeric:
int main()
{
printWelcome("BattleQuest"); // bad: game name might be used elsewhere or change
}
Some literal values are obvious in context and aren't considered magic:
int playerId { 0 }; // ok: clearly starting at 0
playerId = playerId + 1; // ok: obviously incrementing
Other numbers might be self-explanatory:
int milesToKilometers(int miles)
{
return miles * 1609; // ok: clearly a conversion factor
}
Sequential numbers used as identifiers typically aren't magic:
int main()
{
// ok: these are just sequential identifiers
displayCharacter(1); // naming this character1 wouldn't add clarity
displayCharacter(2);
}
Avoid magic numbers in your code (use constexpr variables instead).
Summary
- Literals are fixed values written directly in your code that cannot change
- Default types: Integer literals are
int, floating point literals aredouble, boolean literals arebool, and character literals arechar - Suffixes let you change a literal's type (e.g.,
42ufor unsigned int,3.14ffor float) - Floating point literals: By default are type
double, use thefsuffix to createfloatliterals - Scientific notation: Use
efor exponents (e.g.,5.97e24represents 5.97 × 10²⁴) - String literals: Use double quotes for C-style string literals, which include a hidden null terminator
- Magic numbers: Avoid using literals with unclear meaning or values that might change - use named constants instead
- Best practices: Use uppercase
Lfor long literals, always usefsuffix for float literals, and replace magic numbers with symbolic constants
Understanding literals is fundamental to C++ programming. Using appropriate literal types and avoiding magic numbers makes your code clearer and easier to maintain.
Literals - Quiz
Test your understanding of the lesson.
Practice Exercises
Working with Literals
Practice using different types of literals including integer, floating-point, character, and string literals.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!