Chuyển tới nội dung chính

Prefix và Suffix

String Prefixes (Tiền tố chuỗi)

Các tiền tố (prefix) dùng trước ký tự và chuỗi trong C++

Tiền tốÝ nghĩaKiểu dữ liệuKích thước phần tửMã hóaVí dụ
(trống)Chuỗi/ký tự mặc địnhchar (ký tự), char[] (chuỗi)1 byteASCII hoặc mã hóa hệ thống'a', "hello"
LChuỗi/ký tự rộngwchar_t2 hoặc 4 bytes (phụ thuộc nền tảng)UTF-16 (Windows) hoặc UTF-32 (Linux)L'a', L"hello"
uChuỗi/ký tự Unicode 16-bitchar16_t2 bytesUTF-16u'a', u"hello"
UChuỗi/ký tự Unicode 32-bitchar32_t4 bytesUTF-32U'a', U"hello"
u8Chuỗi UTF-8char (C++20: char8_t)1 byteUTF-8u8"a", u8"hello"
RChuỗi thôconst char*N/AASCII hoặc mã hóa hệ thốngR"C:\user\Admin"

Giải thích chi tiết

  1. Không tiền tố (trống):
    • Dùng cho ký tự (char) hoặc chuỗi (char[]) thông thường.
    • Mã hóa phụ thuộc hệ thống (thường là ASCII hoặc mã hóa mặc định).
    • Phù hợp với văn bản tiếng Anh cơ bản hoặc khi không cần hỗ trợ Unicode.
    • Lưu ý: Không đảm bảo hỗ trợ ký tự tiếng Việt nếu mã hóa hệ thống không phải UTF-8.
  2. L (Wide character/string):
    • Dùng cho ký tự (wchar_t) hoặc chuỗi rộng (wchar_t[]).
    • Kích thước phụ thuộc nền tảng: Windows (2 bytes, UTF-16), Linux (4 bytes, UTF-32).
    • Thích hợp cho ứng dụng đa ngôn ngữ trên Windows (API Win32).
    • Lưu ý: Kích thước không đồng nhất, cần cẩn thận khi chuyển đổi.
  3. u (UTF-16):
    • Dùng cho ký tự (char16_t) hoặc chuỗi Unicode 16-bit.
    • Đảm bảo mã hóa UTF-16, phù hợp với văn bản Unicode cố định.
    • Lưu ý: Ít dùng trực tiếp, thường dùng trong thư viện hoặc xử lý văn bản.
  4. U (UTF-32):
    • Dùng cho ký tự (char32_t) hoặc chuỗi Unicode 32-bit.
    • Mã hóa UTF-32, đảm bảo kích thước cố định (4 bytes).
    • Phù hợp khi cần xử lý toàn bộ điểm mã Unicode (code points).
    • Lưu ý: Tốn bộ nhớ hơn u8.
  5. u8 (UTF-8):
    • Dùng cho chuỗi UTF-8 (char hoặc char8_t từ C++20).
    • Tiết kiệm bộ nhớ, tương thích tốt với hệ thống hiện đại.
    • Lý tưởng cho ứng dụng web, tệp văn bản, hoặc hỗ trợ tiếng Việt.
    • Lưu ý: C++20 giới thiệu char8_t để phân biệt rõ ràng chuỗi UTF-8.
  6. R (Raw String Literal):
    • Chỉ định một chuỗi ký tự thô, cho phép viết chuỗi mà không cần escape các ký tự đặc biệt (như \n, \t, \"). Chuỗi được giữ nguyên như cú pháp trong mã.
    • Dùng cho đường dẫn file Windows, regex, JSON, hoặc chuỗi chứa nhiều ký tự đặc biệt.
    • Kết hợp R với các tiền tố khác:
      • u8R (Raw UTF-8 String Literal):
        • Ý nghĩa: Chuỗi UTF-8 thô, không cần escape.
        • Kiểu dữ liệu: const char* (C++11-17) hoặc const char8_t* (C++20).
        • Ứng dụng: Chuỗi UTF-8 chứa ký tự đặc biệt, như JSON hoặc regex tiếng Việt.
      • uR (Raw UTF-16 String Literal):
        • Ý nghĩa: Chuỗi UTF-16 thô, không cần escape.
        • Kiểu dữ liệu: const char16_t*.
        • Ứng dụng: Hiếm dùng trên Windows, nhưng hữu ích trong ứng dụng cross-platform.
      • UR (Raw UTF-32 String Literal):
        • Ý nghĩa: Chuỗi UTF-32 thô, không cần escape.
        • Kiểu dữ liệu: const char32_t*.
        • Ứng dụng: Xử lý Unicode đầy đủ với chuỗi chứa ký tự đặc biệt.
      • LR (Raw Wide String Literal):
        • Ý nghĩa: Chuỗi rộng (UTF-16 trên Windows) thô, không cần escape.
        • Kiểu dữ liệu: const wchar_t*.
        • Ứng dụng: Dùng với Windows API (Win32, COM) khi cần chuỗi Unicode chứa ký tự đặc biệt.

Ví dụ

#include <iostream>
#include <string>

int main() {
// Không tiền tố: Chuỗi ASCII
const char* str1 = "Xin chào";
std::cout << str1 << std::endl;

// L: Chuỗi rộng
const wchar_t* str2 = L"Xin chào";
std::wcout << str2 << std::endl;

// u: Chuỗi UTF-16
const char16_t* str3 = u"Xin chào";
std::cout << "UTF-16 string length: " << std::u16string(str3).length() << std::endl;

// U: Chuỗi UTF-32
const char32_t* str4 = U"Xin chào";
std::cout << "UTF-32 string length: " << std::u32string(str4).length() << std::endl;

// u8: Chuỗi UTF-8
const char8_t* str5 = u8"Xin chào";
// Chuyển đổi sang std::string để in
std::string str5_converted(reinterpret_cast<const char*>(str5));
std::cout << str5_converted << std::endl;

const char* rawStr = R"(C:\Program Files\nNoEscape)";
std::cout << rawStr << std::endl; // In: C:\Program Files\nNoEscape

const char8_t* rawUtf8 = u8R"(Xin chào\nViệt Nam!)";
// Chuyển đổi sang std::string để in
std::string str(reinterpret_cast<const char*>(rawUtf8));
std::cout << str << std::endl; // In: Xin chào\nViệt Nam!

return 0;
}

Number suffixes (Hậu tố số)

Các hậu tố (suffix) dùng sau số nguyên và số thực trong C++

Hậu tốÝ nghĩaKiểu dữ liệuVí dụ
(trống)Số nguyên hoặc số thực mặc địnhint hoặc double42, 3.14
u hoặc USố nguyên không dấuunsigned int42u, 42U
l hoặc LSố nguyên dàilong42l, 42L
ul hoặc ULSố nguyên dài không dấuunsigned long42ul, 42UL
ll hoặc LLSố nguyên rất dàilong long42ll, 42LL
ull hoặc ULLSố nguyên rất dài không dấuunsigned long long42ull, 42ULL
f hoặc FSố thực độ chính xác đơnfloat3.14f, 3.14F
l hoặc LSố thực độ chính xác caolong double3.14l, 3.14L

Giải thích ghi chú

  1. Mặc định (không hậu tố):
    • Số nguyên: int (thường 4 bytes, phụ thuộc nền tảng).
    • Số thực: double (thường 8 bytes, độ chính xác cao hơn float).
    • Ví dụ: 42int, 3.14double.
  2. Phân biệt hoa/thường:
    • Không có khác biệt giữa uU, lL, llLL, fF.
    • Khuyến nghị: Dùng chữ hoa (U, L, ULL, F) để dễ đọc và thống nhất.
  3. Kết hợp hậu tố:
    • Chỉ áp dụng cho số nguyên: ul (unsigned long), ull (unsigned long long).
    • Không có kết hợp cho số thực (ví dụ: không có fl).
  4. Lưu ý quan trọng:
    • Số nguyên quá lớn mà không có hậu tố ll/ull có thể gây lỗi biên dịch (overflow).
    • Số thực không có hậu tố là double, cần f để ép kiểu thành float.
    • Kiểm tra kích thước kiểu dữ liệu bằng sizeof khi làm việc trên nhiều nền tảng.

Ví dụ

#include <iostream>

int main() {
// Số nguyên mặc định
int x = 42; // int
std::cout << "int: " << x << ", size: " << sizeof(x) << " bytes\n";

// Số nguyên không dấu
unsigned int y = 42U; // unsigned int
std::cout << "unsigned int: " << y << ", size: " << sizeof(y) << " bytes\n";

// Số nguyên dài
long z = 42L; // long
std::cout << "long: " << z << ", size: " << sizeof(z) << " bytes\n";

// Số nguyên rất dài không dấu
unsigned long long w = 42ULL; // unsigned long long
std::cout << "unsigned long long: " << w << ", size: " << sizeof(w) << " bytes\n";

// Số thực độ chính xác đơn
float f = 3.14f; // float
std::cout << "float: " << f << ", size: " << sizeof(f) << " bytes\n";

// Số thực độ chính xác cao
long double ld = 3.14L; // long double
std::cout << "long double: " << ld << ", size: " << sizeof(ld) << " bytes\n";

return 0;
}

Hậu tố z/Z (C++23, Signed Size Type)

  • Ý nghĩa: Chỉ định số nguyên có kích thước phù hợp với kiểu std::size_t (hoặc kiểu signed tương ứng, như std::ssize_t).
  • Kiểu dữ liệu: Kiểu signed tương ứng với std::size_t (thường là long hoặc long long, tùy nền tảng).
  • Ứng dụng: Dùng khi cần số nguyên có kích thước phù hợp với kích thước bộ nhớ (như chỉ số mảng, kích thước container).
  • Ví dụ:
    #include <iostream>
    int main() {
    auto x = 42z; // Kiểu signed tương ứng với size_t
    std::cout << "Value: " << x << ", Size: " << sizeof(x) << " bytes\n";
    return 0;
    }

Hậu tố uz/UZ (C++23, Unsigned Size Type)

  • Ý nghĩa: Chỉ định số nguyên không dấu có kích thước phù hợp với std::size_t.
  • Kiểu dữ liệu: std::size_t (thường là unsigned long hoặc unsigned long long).
  • Ứng dụng: Dùng cho các giá trị không âm, như kích thước mảng hoặc chỉ số.
  • Ví dụ:
    #include <iostream>
    int main() {
    auto x = 42uz; // std::size_t
    std::cout << "Value: " << x << ", Size: " << sizeof(x) << " bytes\n";
    return 0;
    }

Hậu tố cho số bát phân và nhị phân

  • Số bát phân: Bắt đầu bằng 0 (không phải hậu tố, mà là tiền tố cơ số).
    • Ví dụ: 042 là 34 (cơ số 10), kiểu int.
  • Số nhị phân: Bắt đầu bằng 0b hoặc 0B (C++14 trở lên).
    • Ví dụ: 0b1010 là 10 (cơ số 10), kiểu int.