Literals

Literal Constants

Literal || Literal constants are values that are directly written in the source code and represent fixed values. These constants are  “hard-coded" and do not change during the program's execution.

return 5;                     // 5 is an integer literal
bool myNameIsAlex { true };   // true is a boolean literal
double d { 3.4 };             // 3.4 is a double literal
std::cout << "Hello, world!"; // "Hello, world!" is a C-style string literal

Literals are sometimes called literals constants because their meaning cannot be redefined (5 always means the integral value 5).

The type of a literal

Just like objects have a type, all literals have a type. The type of a literal is deduced from the literal's value. For example, a literal that is a whole number (e.g. 5) is deduced to be of type int.

Literal ValueExamplesDefault literal type
integer value5, 0, -3int 
boolean valuetrue, falsebool
floating point value1.2, 0.0, 3.14double (not float)
character‘a’, ‘\n’char
C-style string“Hi, buddy!”const char[10]

Types of Literals in C and C++

  1. Integer Literals
  2. Floating-Point Literals
  3. Character Literals
  4. String Literals
  5. Boolean Literals
  6. User-Defined Literals (C++11 and later)

1️⃣ Integer Literals

Integer literals represent whole numbers (numbers without fractional components). Integer literals can be expressed in different number systems: decimal, octal, hexadecimal, and binary (C++14 and later).

Types of Integer Literals:

  1. Decimal (Base 10): Numbers that are composed of digits 0-9.
    • Decimal literals are the most common type of integer literal, representing numbers in base 10. These numbers consist of digits 0-9 without any prefix.
    • int a = 42;  // Decimal literal
      int b = 12345;  // Another decimal literal
      
  2. Octal (Base 8): Numbers that start with a 0 followed by digits 0-7.
    • Octal literals are represented in base 8, consisting of digits 0-7. In both C and C++, octal numbers are denoted by a leading 0 (zero).
    • int octal_num = 052;  // Octal literal (equivalent to decimal 42)
      int another_octal = 0755;  // Common for file permissions (equivalent to decimal 493)
    • In the above example, 052 is an octal literal that is equivalent to 42 in decimal.
  3. Hexadecimal (Base 16): Numbers that start with 0x or 0X followed by digits 0-9 and letters A-F/a-f (representing values 10-15).
    • Hexadecimal literals represent numbers in base 16, consisting of digits 0-9 and letters A-F/a-f (representing values 10-15). Hexadecimal literals are prefixed with 0x or 0X.
    • int hex_num = 0x2A;  // Hexadecimal literal (equivalent to decimal 42)
      int color_code = 0xFF5733;  // Common in graphics programming
      
    • In this example, 0x2A is equivalent to 42 in decimal, and 0xFF5733 is often used in color representations in graphics.
  4. Binary (Base 2): C++14 introduced binary literals, starting with 0b or 0B followed by digits 0 and 1.
    • int bin_num = 0b101010;  // Binary literal (equivalent to decimal 42)
      int flag_mask = 0b1101;  // Another binary literal
      
    • In this case, 0b101010 is equivalent to 42 in decimal.
Example:
// Example program
#include <iostream>

using namespace std;

int main()
{
    int decimalLiteral = 42; // Decimal literal
    cout << "decimalLiteral = " << decimalLiteral << endl;
    
    int octalLiteral = 052; // Octal literal (52 in octal is 42 in decimal)
    cout << "octalLiteral = " << octalLiteral << endl;
    
    int hexLiteral = 0x2A; // Hexadecimal literal (2A in hex is 42 in decimal)
    cout << "hexLiteral = " << hexLiteral << endl;
    
    int binaryLiteral = 0b101010; // Binary literal (101010 in binary is 42 in decimal)
    cout << "binaryLiteral = " << binaryLiteral << endl;
    
}
Output:
decimalLiteral = 42
octalLiteral = 42
hexLiteral = 42
binaryLiteral = 42

Integer Literal Suffixes:

Integer literals can be suffixed to indicate their size (standard, long, or long long) and whether they are signed or unsigned.

What's the use of Integer Literal 

The use of suffixes in integer literals in C and C++ helps the compiler determine the type and size of the literal at compile-time. By default, literals are treated as int type (or double for floating-point literals). However, in certain cases, you may need a different integer type—such as long, unsigned, or long long—to represent larger values or to control signedness. Suffixes provide an explicit way to specify these types.

Common Integer Suffixes:

  • U or u: Unsigned integer
  • L or l: Long integer
  • LL or ll: Long long integer
unsigned int u = 42U;   // Unsigned integer
long int l = 42L;       // Long integer
long long int ll = 42LL;  // Long long integer

Combining Suffixes:

You can combine suffixes to define literals with specific characteristics. For example:

unsigned long int ul = 42UL;  // Unsigned long integer
unsigned long long int ull = 42ULL;  // Unsigned long long integer
SuffixType
(none)int
Uunsigned int
Llong int
ULunsigned long int
LLlong long int
ULLunsigned long long int

2️⃣ Floating-Point Literals

Floating-point literals represent numbers with fractional parts, written using a decimal point or in scientific notation.

Types of Floating-Point Literals:

  • Decimal Form: A real number with a fractional part.
  • Scientific Notation (Exponential Form): Represents very large or very small numbers using e or E followed by an exponent.
Example:
double d1 = 3.14;         // Simple decimal floating-point literal
double d2 = 1.5e6;        // Scientific notation (1.5 * 10^6)
double d3 = 1.2E-3;       // Scientific notation with negative exponent (1.2 * 10^-3)

 3️⃣Character Literals

Character literals represent single characters enclosed in single quotes (' '). These literals are of type char and store a single character, which could be a letter, a digit, or punctuation mark, or a special symbol.

Types of Character Literals:

  • Single-byte Character Literal: Represents a single ASCII character.
  • Escape Sequences: Special characters that represent actions or non-printable characters, starting with a backslash (\).

Common Escape Sequences:

Escape SequenceDescription
\'Single quote
\"Double quote
\\Backslash
\nNewline
\tHorizontal tab
\rCarriage return
\0Null character
Example:
char ch = 'A';        // Single character literal
char digit = '7';     // Character representing a digit
char newline = '\n';  // Escape sequence for newline
char specialChar = '$'; // Special character
char tab = '\t';    // Horizontal tab character
char backslash = '\\'; // Backslash character

Character Literals and Integers: Character literals are internally represented as integers, corresponding to their ASCII values. For example, 'A' corresponds to 65 in ASCII.

#include <iostream>

using namespace std;

int main()
{
    char ch = 'A';       // Character literal 'A'
    int asciiValue = 'A'; // ASCII value of 'A' is 65
    
    cout << "ch = " << ch << endl;
    cout << "asciiValue = " << asciiValue << endl;
}
Output
ch = A
asciiValue = 65

Wide Character Literals:

For extended character sets, wide character literals can be created by prefixing the character literal with an L.

wchar_t wch = L'Ω';  // Wide character literal

Unicode Character Literals:

C++11 introduced Unicode literals:

  • u' ': 16-bit Unicode character (UTF-16)
  • U' ': 32-bit Unicode character (UTF-32)
char16_t u16_ch = u'Ω';  // UTF-16 Unicode literal
char32_t u32_ch = U'Ω';  // UTF-32 Unicode literal

4️⃣ String Literals

String literals represent sequences of characters enclosed in double quotes (" "). In C and C++, string literals are automatically terminated with a null character (\0), which marks the end of the string or we can say that they are array of characters terminated by a null character (\0).

Example:

const char* str = "Hello, World!";  // String literal
String Literals with Escape Sequences:
const char* path = "C:\\Program Files\\MyApp\\data.txt";  // Escape sequence for backslash

Multiline String Literals (C++11 Raw String Literals):

C++11 introduced raw string literals, which preserve the literal characters as written and ignore escape sequences. Raw string literals start with R"( and end with )".

const char* raw_str = R"(C:\Program Files\MyApp\data.txt)";  // Raw string literal, no need for escape sequences

Wide and Unicode String Literals:

String literals can also represent wide or Unicode character sequences:

  • Wide String Literals: Prefix with L to define wide strings (for wide characters).
  • UTF-16 String Literals: Prefix with u.
  • UTF-32 String Literals: Prefix with U.
const wchar_t* wstr = L"Hello";  // Wide string literal
const char16_t* u16_str = u"Hello";  // UTF-16 string literal (C++11)
const char32_t* u32_str = U"Hello";  // UTF-32 string literal (C++11)

5️⃣ Boolean Literals

C++ introduced the bool type and two boolean literals: true and false. These literals represent the logical states of truth and falsehood, with true converting to 1 and false converting to 0.

Example:

bool flag = true;  // Boolean literal

6️⃣ User-Defined Literals (C++11 and later)

C++11 introduced the concept of user-defined literals, which allows developers to create their own literal types. User-defined literals extend the capability of literal constants to represent non-built-in types, such as complex numbers, durations, or distances.

Syntax for User-Defined Literals:

Type operator"" _suffix(args);

Example of User-Defined Literals:

long double operator"" _km(long double distance) {
    return distance * 1000;  // Convert kilometers to meters
}

int main() {
    long double distance = 1.5_km;  // 1.5 kilometers
}

In this example, we define a user-defined literal _km to convert kilometers to meters. Now, 1.5_km can be used to express distances in kilometers directly in the code.

7️⃣ Pointer Literal (nullptr)

The null pointer literal in C++ is represented by nullptr, which was introduced in C++11. It is used to represent a null pointer, meaning a pointer that doesn’t point to any valid memory location.

Example:
int* ptr = nullptr;  // Null pointer literal

Before C++11, the literal 0 or the macro NULL was used to represent a null pointer, but nullptr is preferred because it has a specific type (std::nullptr_t), reducing ambiguity.

A little history of nullptr:

nullptr is a keyword introduced in C++11 that represents a null pointer, meaning a pointer that doesn't point to any valid object or memory address. It replaces the older use of NULL and 0 to represent null pointers, offering a more type-safe and explicit way to express the concept of a null pointer.

Key Differences Between nullptr, NULL, and 0:

Before C++11, null pointers were represented by either the NULL macro or the literal 0. However, both had limitations that could lead to bugs or ambiguity in code.

  • 0: Before C++11, the literal 0 was commonly used to represent null pointers. However, 0 is also a valid integer, which could cause confusion and errors in overloaded functions or template code.
  • NULL: The NULL macro, defined in the C++ standard library, is essentially a synonym for 0 (or (void*)0 in C). This suffers from the same issues as using 0 because NULL is also treated as an integer in some contexts.
  • nullptr: With C++11, nullptr was introduced as a dedicated keyword to represent null pointers, providing a clearer and safer alternative that avoids the ambiguity associated with 0 and NULL.