Выражение char16_t и char32_t

В C11 поддержка переносимых типов широких символов char16_t а также char32_t добавлены для UTF-16 и UTF-32 соответственно.

Тем не менее, в техническом отчете нет упоминания о порядке байтов для этих двух типов.

Например, следующий фрагмент в gcc-4.8.4 на моем компьютере x86_64 при компиляции с -std=c11:

#include <stdio.h>
#include <uchar.h>

char16_t utf16_str[] = u"十六";  // U+5341 U+516D
unsigned char *chars = (unsigned char *) utf16_str;
printf("Bytes: %X %X %X %X\n", chars[0], chars[1], chars[2], chars[3]);

будет производить

Bytes: 41 53 6D 51

Что означает, что это мало порядковый номер.

Но зависит ли это поведение от платформы / реализации: всегда ли оно соответствует порядку действий платформы, или может какая-то реализация решит всегда реализовывать char16_t а также char32_t в big-endian?

2 ответа

Решение

char16_t а также char32_t не гарантируйте кодировку Unicode. (Это особенность C++.) Макросы __STDC_UTF_16__ а также __STDC_UTF_32__соответственно, указывают, что кодовые точки Unicode фактически определяют символьные значения фиксированного размера. См. C11 §6.10.8.2 для этих макросов.

(Кстати, __STDC_ISO_10646__ указывает на то же самое для wchar_t, а также показывает, какая версия Unicode реализована с помощью wchar_t, Конечно, на практике компилятор просто копирует кодовые точки из исходного файла в строки в объектном файле, поэтому ему не нужно много знать о конкретных символах.)

Учитывая, что действует кодировка Unicode, значения кодовых точек сохраняются в char16_t или же char32_t должен иметь то же представление объекта, что и uint_least16_t а также uint_least32_tпотому что они определены как typedef псевдонимы для этих типов, соответственно (C11 §7.28). Это опять-таки несколько отличается от C++, который выделяет эти типы, но явно требует совместимого представления объектов.

В результате да, в этом нет ничего особенного char16_t а также char32_t, Они являются обычными целыми числами в порядке следования платформ.

Однако ваша тестовая программа не имеет ничего общего с порядком байтов. Он просто использует значения широких символов без проверки того, как они отображаются в байтах в памяти.

Тем не менее, в техническом отчете нет упоминания о порядке байтов для этих двух типов.

В самом деле. Стандарт C не особо определяет представление многобайтовых символов в исходных файлах.

char16_t utf16_str[] = u"十六"; // U+5341 U+516D
printf("U+%X U+%X\n", utf_16_str[0], utf_16_str[1]);

будет производить U+5341 U+516D. Это означает, что он имеет порядок байтов.

Но зависит ли это поведение от платформы / реализации: всегда ли оно соответствует порядку действий платформы, или может какая-то реализация решит всегда реализовывать char16_t а также char32_t в big-endian?

Да, поведение зависит от реализации, как вы это называете. См. C11§5.1.1.2:

Многобайтовые символы физического исходного файла отображаются, в зависимости от реализации, в исходный набор символов (ввод символов новой строки для индикаторов конца строки), если это необходимо.

То есть, считаются ли многобайтовые символы в вашем исходном коде с прямым или прямым порядком байтов определяемыми реализацией. Я бы посоветовал использовать что-то вроде u"\u5341\u516d", если переносимость является проблемой.

UTF-16 и UTF-32 не имеют определенного порядка байтов. Они обычно кодируются в собственном порядке байтов хоста. Вот почему в начале строки имеются маркеры порядка байтов (BOM), которые могут указывать порядковый номер строки UTF-16 или UTF-32.

Другие вопросы по тегам