CodeNebula
C++11coreintermediate

char16_t/char32_t (C++11 Addition)

C++11 · Modern Revolution · Compiler flag: -std=c++11

Explanation

New character types `char16_t` and `char32_t` provide guaranteed-width types for UTF-16 and UTF-32 encoded characters, enabling portable Unicode handling.

Real-World Scenario

Process internationalized text data from a database that stores content in UTF-16 encoding.

Quick Snippet

snippet.cpp
char16_t c16 = u'A';       // UTF-16 character
char32_t c32 = U'\U0001F600'; // UTF-32 character (emoji)

Full Example

char16_char32.cpp
// CodeNebula - C++11 Example: char16_t and char32_t Types
// Compile: g++ -std=c++11 -Wall -Wextra -o example char16_char32.cpp
//
// This example demonstrates:
// - char16_t for UTF-16 encoded characters
// - char32_t for UTF-32 encoded characters
// - Size and alignment differences from char and wchar_t
// - Basic operations on these character types
// - u'' and U'' character literals

#include <iostream>
#include <cstdint>
#include <string>

// ============================================================
// 1. Helper to print code point values
// ============================================================
void printCodePoint(const char* label, char32_t cp) {
    std::cout << "  " << label << ": U+"
              << std::hex << static_cast<uint32_t>(cp)
              << " (decimal " << std::dec << static_cast<uint32_t>(cp) << ")"
              << std::endl;
}

// ============================================================
// 2. Working with char16_t
// ============================================================
void demonstrateChar16() {
    std::cout << "--- char16_t ---" << std::endl;
    std::cout << "  sizeof(char16_t): " << sizeof(char16_t) << " bytes" << std::endl;
    std::cout << "  alignof(char16_t): " << alignof(char16_t) << std::endl;

    // Basic Latin characters
    char16_t letterA = u'A';
    char16_t digit5 = u'5';
    char16_t euro = u'\u20AC';  // Euro sign

    std::cout << "  u'A' value: " << static_cast<uint16_t>(letterA) << std::endl;
    std::cout << "  u'5' value: " << static_cast<uint16_t>(digit5) << std::endl;
    std::cout << "  Euro sign (U+20AC) value: " << static_cast<uint16_t>(euro) << std::endl;

    // char16_t string (u"...")
    const char16_t* greeting = u"Hello";
    size_t len = 0;
    while (greeting[len] != u'\0') ++len;
    std::cout << "  u\"Hello\" length: " << len << " code units" << std::endl;
}

// ============================================================
// 3. Working with char32_t
// ============================================================
void demonstrateChar32() {
    std::cout << "\n--- char32_t ---" << std::endl;
    std::cout << "  sizeof(char32_t): " << sizeof(char32_t) << " bytes" << std::endl;
    std::cout << "  alignof(char32_t): " << alignof(char32_t) << std::endl;

    // Each char32_t holds exactly one Unicode code point
    char32_t smiley = U'\U0001F600';       // Grinning face
    char32_t musicNote = U'\U0001D11E';    // Musical symbol G clef
    char32_t heartSuit = U'\u2665';        // Heart suit

    printCodePoint("Smiley face", smiley);
    printCodePoint("G clef", musicNote);
    printCodePoint("Heart suit", heartSuit);

    // char32_t string (U"...")
    const char32_t* text = U"ABC\U0001F600";
    size_t len = 0;
    while (text[len] != U'\0') ++len;
    std::cout << "  U\"ABC<smiley>\" length: " << len << " code points" << std::endl;
}

// ============================================================
// 4. Comparison of character type sizes
// ============================================================
void compareSizes() {
    std::cout << "\n--- Size comparison ---" << std::endl;
    std::cout << "  sizeof(char):     " << sizeof(char) << " byte(s)" << std::endl;
    std::cout << "  sizeof(wchar_t):  " << sizeof(wchar_t) << " byte(s)" << std::endl;
    std::cout << "  sizeof(char16_t): " << sizeof(char16_t) << " byte(s)" << std::endl;
    std::cout << "  sizeof(char32_t): " << sizeof(char32_t) << " byte(s)" << std::endl;

    // char16_t and char32_t have guaranteed sizes
    static_assert(sizeof(char16_t) == 2, "char16_t must be 2 bytes");
    static_assert(sizeof(char32_t) == 4, "char32_t must be 4 bytes");
    std::cout << "  static_assert: sizes verified at compile time" << std::endl;
}

int main() {
    std::cout << "=== char16_t and char32_t Types ===" << std::endl;

    demonstrateChar16();
    demonstrateChar32();
    compareSizes();

    // Arithmetic on code points
    std::cout << "\n--- Code point arithmetic ---" << std::endl;
    char32_t base = U'A';
    for (int i = 0; i < 5; ++i) {
        char32_t ch = base + static_cast<char32_t>(i);
        std::cout << "  U'A' + " << i << " = code point "
                  << static_cast<uint32_t>(ch) << std::endl;
    }

    return 0;
}

// Expected output:
// === char16_t and char32_t Types ===
// --- char16_t ---
//   sizeof(char16_t): 2 bytes
//   alignof(char16_t): 2
//   u'A' value: 65
//   u'5' value: 53
//   Euro sign (U+20AC) value: 8364
//   u"Hello" length: 5 code units
//
// --- char32_t ---
//   sizeof(char32_t): 4 bytes
//   alignof(char32_t): 4
//   Smiley face: U+1f600 (decimal 128512)
//   G clef: U+1d11e (decimal 119070)
//   Heart suit: U+2665 (decimal 9829)
//   U"ABC<smiley>" length: 4 code points
//
// --- Size comparison ---
//   sizeof(char):     1 byte(s)
//   sizeof(wchar_t):  4 byte(s)
//   sizeof(char16_t): 2 byte(s)
//   sizeof(char32_t): 4 byte(s)
//   static_assert: sizes verified at compile time
//
// --- Code point arithmetic ---
//   U'A' + 0 = code point 65
//   U'A' + 1 = code point 66
//   U'A' + 2 = code point 67
//   U'A' + 3 = code point 68
//   U'A' + 4 = code point 69
Run command
g++ -std=c++11 -Wall -Wextra -o example char16_char32.cpp