C ++ utf-8 литералы в G CC и MSVC - PullRequest
2 голосов
/ 29 апреля 2020

Здесь у меня есть простой код:

#include <iostream>
#include <cstdint>

    int main()
    {
         const unsigned char utf8_string[] = u8"\xA0";
         std::cout << std::hex << "Size: " << sizeof(utf8_string) << std::endl;
          for (int i=0; i < sizeof(utf8_string); i++) {
            std::cout << std::hex << (uint16_t)utf8_string[i] << std::endl;
          }
    }

Я вижу другое поведение здесь с MSV C и G CC. MSV C видит "\xA0" как некодированную последовательность Unicode и кодирует ее в utf-8. Таким образом, в MSV C вывод будет:

C2A0

, который правильно закодирован в символе Unicode utf8 U+00A0.

Но в случае G CC ничего не происходит. Он обрабатывает строку как простые байты. Там нет никаких изменений, даже если я удаляю u8 перед строковым литералом.

Оба компилятора кодируют в utf8 с выводом C2A0, если строка установлена ​​в: u8"\u00A0";

Почему компиляторы ведут себя иначе и что на самом деле делает это правильно?

Программное обеспечение, используемое для теста:

G CC 8.3.0

MSV C 19.00.23506

C ++ 11

1 Ответ

1 голос
/ 10 мая 2020

Они оба не правы.

Насколько я могу судить, стандарт C ++ 17 гласит здесь , что:

Размер узкий строковый литерал - это общее количество escape-последовательностей и других символов, плюс как минимум один для многобайтовой кодировки каждого универсального имени символа, плюс один для завершающего '\ 0'.

Хотя есть и другие подсказки, это, кажется, самый сильный признак того, что escape-последовательности не являются многобайтовыми и что поведение MSV C является неправильным.

Есть билеты для этого, которые в настоящее время помечены как Under Расследование:

Однако также говорится здесь о литералах UTF-8, которые:

Если значение не может быть представлено ни одной кодовой единицей UTF-8, программа некорректна.

Поскольку 0xA0 не является допустимым символом UTF-8, программа не должна компилироваться.

Обратите внимание:

  • Литералы UTF-8, начинающиеся с u8, определяются как узкие.
  • \xA0 является escape-последовательностью
  • \u00A0 считается универсальным именем символа, а не escape-последовательностью
...