C99 trở xuống
Tiêu chuẩn C (C99) cung cấp các ký tự rộng và ký tự nhiều byte, nhưng vì không có gì đảm bảo về những ký tự rộng đó có thể chứa, giá trị của chúng có phần hạn chế. Đối với một triển khai nhất định, chúng cung cấp hỗ trợ hữu ích, nhưng nếu mã của bạn phải có thể di chuyển giữa các triển khai, thì không đủ đảm bảo rằng chúng sẽ hữu ích.
Do đó, cách tiếp cận được đề xuất bởi Hans van Eck (là viết một trình bao bọc xung quanh thư viện ICU - International Components for Unicode -) là IMO.
Mã hóa UTF-8 có nhiều ưu điểm, một trong số đó là nếu bạn không làm rối dữ liệu (ví dụ: bằng cách cắt ngắn nó), thì nó có thể được sao chép bởi các hàm không nhận thức đầy đủ về sự phức tạp của UTF-8 mã hóa. Điều này rõ ràng không phải là trường hợp với wchar_t
.
Unicode đầy đủ là định dạng 21 bit. Tức là, Unicode bảo lưu các điểm mã từ U + 0000 đến U + 10FFFF.
Một trong những điều hữu ích về các định dạng UTF-8, UTF-16 và UTF-32 (trong đó UTF là viết tắt của Unicode Transformation Format - xem Unicode ) là bạn có thể chuyển đổi giữa ba dạng biểu diễn mà không bị mất thông tin. Mỗi cái có thể đại diện cho bất cứ thứ gì mà những cái khác có thể đại diện. Cả UTF-8 và UTF-16 đều là định dạng nhiều byte.
UTF-8 được biết đến là một định dạng nhiều byte, với cấu trúc cẩn thận giúp bạn có thể tìm thấy phần đầu của các ký tự trong một chuỗi một cách đáng tin cậy, bắt đầu từ bất kỳ điểm nào trong chuỗi. Các ký tự byte đơn có bit cao được đặt thành 0. Các ký tự nhiều byte có ký tự đầu tiên bắt đầu bằng một trong các mẫu bit 110, 1110 hoặc 11110 (đối với ký tự 2 byte, 3 byte hoặc 4 byte), với các byte tiếp theo luôn bắt đầu bằng 10. Các ký tự tiếp tục luôn nằm trong phạm vi 0x80 .. 0xBF. Có các quy tắc rằng các ký tự UTF-8 phải được trình bày ở định dạng tối thiểu có thể. Một hệ quả của các quy tắc này là các byte 0xC0 và 0xC1 (cũng 0xF5..0xFF) không thể xuất hiện trong dữ liệu UTF-8 hợp lệ.
U+0000 .. U+007F 1 byte 0xxx xxxx
U+0080 .. U+07FF 2 bytes 110x xxxx 10xx xxxx
U+0800 .. U+FFFF 3 bytes 1110 xxxx 10xx xxxx 10xx xxxx
U+10000 .. U+10FFFF 4 bytes 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
Ban đầu, người ta hy vọng rằng Unicode sẽ là một bộ mã 16 bit và mọi thứ sẽ phù hợp với không gian mã 16 bit. Thật không may, thế giới thực phức tạp hơn và nó phải được mở rộng sang mã hóa 21-bit hiện tại.
UTF-16 do đó là một bộ mã đơn vị (từ 16 bit) cho 'Mặt phẳng đa ngôn ngữ cơ bản', có nghĩa là các ký tự có mã Unicode điểm U + 0000 .. U + FFFF, nhưng sử dụng hai đơn vị (32 bit) cho ký tự bên ngoài phạm vi này. Do đó, mã hoạt động với mã hóa UTF-16 phải có khả năng xử lý các mã hóa độ rộng thay đổi, giống như UTF-8 phải. Các mã cho các ký tự đơn vị kép được gọi là mã thay thế.
Đại diện là các điểm mã từ hai dải giá trị Unicode đặc biệt, được dành riêng để sử dụng làm giá trị đầu và giá trị theo sau của các đơn vị mã được ghép nối trong UTF-16. Các đại diện thay thế hàng đầu, còn được gọi là cao, là từ U + D800 đến U + DBFF và các đại diện thay thế ở cuối, hoặc thấp là từ U + DC00 đến U + DFFF. Chúng được gọi là đại diện, vì chúng không đại diện trực tiếp cho các ký tự mà chỉ là một cặp.
Tất nhiên, UTF-32 có thể mã hóa bất kỳ điểm mã Unicode nào trong một đơn vị lưu trữ. Nó hiệu quả cho tính toán nhưng không hiệu quả để lưu trữ.
Bạn có thể tìm thêm nhiều thông tin tại các trang web ICU và Unicode.
C11 và <uchar.h>
Tiêu chuẩn C11 đã thay đổi các quy tắc, nhưng không phải tất cả các triển khai đều bắt kịp với những thay đổi ngay cả bây giờ (giữa năm 2017). Tiêu chuẩn C11 tóm tắt những thay đổi để hỗ trợ Unicode như:
- Các ký tự và chuỗi Unicode (
<uchar.h>
) (ban đầu được chỉ định trong ISO / IEC TR 19769: 2004)
Những gì sau đây là một phác thảo tối thiểu về chức năng. Đặc điểm kỹ thuật bao gồm:
6.4.3 Tên ký tự chung
Cú pháp
phổ-ký tự-tên:
\u
hex-quad
\U
hex-quad hex-quad
hex-quad:
thập lục phân-chữ số thập lục phân-chữ số thập lục phân-chữ số thập lục phân-chữ số
7.28 Tiện ích Unicode <uchar.h>
Tiêu đề <uchar.h>
khai báo các kiểu và chức năng để thao tác các ký tự Unicode.
Các kiểu được khai báo là mbstate_t
(mô tả trong 7.29.1) và size_t
(mô tả trong 7.19);
char16_t
là kiểu số nguyên không dấu được sử dụng cho các ký tự 16 bit và cùng kiểu với uint_least16_t
(được mô tả trong 7.20.1.2); và
char32_t
là kiểu số nguyên không dấu được sử dụng cho các ký tự 32 bit và cùng kiểu với uint_least32_t
(cũng được mô tả trong 7.20.1.2).
(Dịch các tham chiếu chéo: <stddef.h>
định nghĩa size_t
,
<wchar.h>
xác định mbstate_t
và <stdint.h>
định nghĩa uint_least16_t
và uint_least32_t
.) <uchar.h>
Tiêu đề cũng xác định một tập hợp tối thiểu các hàm chuyển đổi (có thể khởi động lại):
mbrtoc16()
c16rtomb()
mbrtoc32()
c32rtomb()
Có các quy tắc về các ký tự Unicode có thể được sử dụng trong các mã định danh bằng cách sử dụng ký hiệu \unnnn
hoặc \U00nnnnnn
. Bạn có thể phải tích cực kích hoạt hỗ trợ cho các ký tự như vậy trong mã định danh. Ví dụ: GCC yêu cầu -fextended-identifiers
cho phép những điều này trong số nhận dạng.
Lưu ý rằng macOS Sierra (10.12.5), với tên gọi nhưng một nền tảng, không hỗ trợ <uchar.h>
.