C++ Constants/Literals
C++ Constants and Literals
Section titled “C++ Constants and Literals”Literals (often called constants) are fixed values directly embedded in the source code. They represent specific data like numbers, characters, or strings.
Constants, in a broader sense, are identifiers (like variables) whose values cannot be changed after initialization. Modern C++ offers several ways to define constants.
Literals
Section titled “Literals”C++ supports various types of literals:
1. Integer Literals
Section titled “1. Integer Literals”Represent whole numbers. They can be specified in different bases:
- Decimal (base 10): Default, no prefix (e.g.,
123,-45). - Octal (base 8): Prefix
0(e.g.,0173which is 123 in decimal). Avoid leading zeros unless octal is intended, as it can be confusing. - Hexadecimal (base 16): Prefix
0xor0X(e.g.,0x7Bor0X7b, both are 123 in decimal). Uses digits 0-9 and letters a-f (or A-F). - Binary (base 2) (C++14): Prefix
0bor0B(e.g.,0b01111011which is 123 in decimal).
Integer literals can have suffixes to specify their type:
uorU:unsigned(e.g.,123u).lorL:long(e.g.,123L).llorLL(C++11):long long(e.g.,123LL).- Combinations are possible (e.g.,
123UL,45ull).
C++14 introduced digit separators (single quotes ') for readability:
long long big_number = 1'000'000'000LL; // Easier to readint binary_flags = 0b1101'0010'1010'0001;2. Floating-Point Literals
Section titled “2. Floating-Point Literals”Represent numbers with a fractional part. They can be written in decimal or exponential notation:
- Decimal: Must include a decimal point (
.) or an exponent (e.g.,3.14159,12.0,.5,5.). - Exponential: Uses
eorEfollowed by an optional sign and an integer exponent (power of 10) (e.g.,6.022e23,1.6E-19). - Hexadecimal floating-point literals (using
0xprefix andpfor exponent) exist but are less common (0x1.921fb5p+1).
Suffixes specify the type:
- No suffix:
double(default). forF:float(e.g.,3.14f).lorL:long double(e.g.,3.1415926535L).
Digit separators (') can also be used (C++14).
double pi = 3.141'592'653'589'793;3. Boolean Literals
Section titled “3. Boolean Literals”Represent truth values:
true: Represents the boolean value true.false: Represents the boolean value false.
4. Character Literals
Section titled “4. Character Literals”Represent single characters, enclosed in single quotes (').
- Plain
char:'a','?','7'. Type ischar. - Wide Character:
L'β'(prefixL). Type iswchar_t. - UTF-8 (C++11):
u8'貓'(prefixu8). Type ischar(C++11/17) orchar8_t(C++20). - UTF-16 (C++11):
u'Ω'(prefixu). Type ischar16_t. - UTF-32 (C++11):
U'🌍'(prefixU). Type ischar32_t.
Escape Sequences: Special characters represented using a backslash (\):
| Escape Sequence | Meaning |
|---|---|
| \ | Backslash (\) character |
| ’ | Single quote (') character |
| ” | Double quote (") character |
| ? | Question mark (?) character |
| \n | Newline |
| \t | Horizontal tab |
| \v | Vertical tab |
| \b | Backspace |
| \r | Carriage return |
| \f | Form feed |
| \a | Alert (bell) |
| \0 | Null character |
| \ooo | Octal value (up to 3 digits) |
| \xhh… | Hexadecimal value |
| \uHHHH (C++11) | Universal character name (Unicode - 16-bit) |
| \UHHHHHHHH (C++11) | Universal character name (Unicode - 32-bit) |
5. String Literals
Section titled “5. String Literals”Represent sequences of characters, enclosed in double quotes ("). They are implicitly null-terminated (a \0 character is automatically appended).
- Plain:
"Hello, World!"(Type isconst char[]). - Wide:
L"你好"(prefixL). Type isconst wchar_t[]. - UTF-8 (C++11):
u8"κόσμε"(prefixu8). Type isconst char[](C++11/17) orconst char8_t[](C++20). - UTF-16 (C++11):
u"नमस्ते"(prefixu). Type isconst char16_t[]. - UTF-32 (C++11):
U"שלום"(prefixU). Type isconst char32_t[]. - Raw String Literals (C++11):
R"(No\escape\needed)"orR"delimiter(Text)delimiter". Useful for strings containing many backslashes or quotes.
Adjacent string literals are concatenated by the compiler:
std::cout << "This is part 1, " "and this is part 2.\n";6. Pointer Literal
Section titled “6. Pointer Literal”nullptr (C++11): Represents the null pointer value. It is type-safe and preferred over 0 or NULL for representing null pointers.
Defining Constants
Section titled “Defining Constants”Constants are named entities whose values cannot change after initialization. Modern C++ offers two primary ways:
1. const Keyword
Section titled “1. const Keyword”The const qualifier declares an object as immutable. Its value must be initialized upon declaration and cannot be modified later. const variables have scope like regular variables.
#include <iostream>
int main() { const int MAX_USERS = 100; const double PI = 3.14159; const char NEWLINE = '\n';
// MAX_USERS = 200; // Error! Cannot assign to const variable.
double circumference = 2 * PI * 5.0; // Use the constant std::cout << "Max users: " << MAX_USERS << NEWLINE; std::cout << "Circumference: " << circumference << NEWLINE;
return 0;}const is preferred over #define for defining constants because it is type-safe and respects scope.
2. constexpr Keyword (C++11)
Section titled “2. constexpr Keyword (C++11)”constexpr declares that an expression can be evaluated at compile time. When applied to a variable, it implies const and requires the initializer to be a compile-time constant expression.
constexpr allows constants to be used in contexts requiring compile-time evaluation, such as array bounds (before C++11 VLAs), template arguments, and enum initializers.
#include <array> // For std::array
constexpr int get_array_size() { return 5 * 2;}
int main() { constexpr int COMPILED_SIZE = 10; constexpr double GRAVITY = 9.80665; constexpr int DYNAMIC_SIZE = get_array_size(); // Evaluated at compile time
int myArray[COMPILED_SIZE]; // OK: COMPILED_SIZE is compile-time constant std::array<double, DYNAMIC_SIZE> stdArray; // OK: DYNAMIC_SIZE is compile-time constant
// GRAVITY = 9.9; // Error! constexpr implies const
return 0;}Best Practice: Prefer constexpr for constants that can be evaluated at compile time. Use const for values initialized at runtime that should not change afterwards.
Avoid #define for Constants
Section titled “Avoid #define for Constants”The preprocessor directive #define can also create symbolic names for values (macros).
#define MAX_ITEMS 10 // Old C-style, avoid for constantsHowever, this is generally discouraged in modern C++ for defining constants because:
- It lacks type information (simple text substitution).
- It does not respect scope (macros are global within the translation unit after definition).
- It can lead to unexpected behavior due to macro expansion rules.
- It isn’t easily debuggable (the debugger sees the substituted value, not the macro name).
Use const or constexpr instead for type safety and better code structure.