Выражение 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.