Подтвердить что ты не робот

Запутывание sizeof (char) по ISO/IEC в кодировке с разными кодировками, например UTF-16

Предполагая, что программа запущена в системе с набором символов кодировки UTF-16. Итак, согласно языку программирования С++ - 4th, стр. 150:

A char может содержать символ набора символов машин.

→ Я думаю, что переменная char будет иметь размер 2 байта.

Но согласно ISO/IEC 14882: 2014:

sizeof(char), sizeof(signed char) и sizeof(unsigned char) равны 1 ".

или язык программирования С++ - четвертый, стр. 149:

"[...], поэтому по определению размер a char равен 1"

→ Он фиксируется с размером 1.

Вопрос: Есть ли конфликт между этими утверждениями выше или является sizeof(char) = 1 просто значением по умолчанию (определение) и будет определяться реализацией зависит от каждой системы?

4b9b3361

Ответ 1

Стандарт С++ (и C, если на то пошло) эффективно определяет byte как размер типа char, а не как восьмибитное количество 1. По C++11 1.7/1 (мой полужирный):

Основным блоком памяти в модели памяти С++ является байт. Байт имеет наименьшее, достаточное для того, чтобы содержать любой член базового набора символов исполнения и восьмибитовых кодовых единиц формы кодировки Unicode UTF-8 и состоит из непрерывной последовательности бит, число которых определяется реализацией.

Следовательно, выражение sizeof(char) всегда равно 1, независимо от того, что.

Если вы хотите увидеть, может ли ваша базовая переменная char (возможно, вариант unsigned лучше всего), может фактически содержать 16-битное значение, элемент, который вы хотите просмотреть, CHAR_BIT от <climits>, Это содержит число бит в переменной char.


1 Многие стандарты, особенно связанные с протоколами связи, используют более точный термин octet для восьмибитового значения.

Ответ 2

Да, существует ряд серьезных конфликтов и проблем с объединением чисел на С++ для char, но и вопрос объединяет некоторые вещи. Таким образом, простой прямой ответ будет напоминать ответ "да", "нет" или "не знать" на вопрос "перестали ли вы избивать свою жену?". Единственный прямой ответ - буддийский "му" , разоблачая вопрос.

Итак, давайте начнем с изучения фактов.


Факты о типе char.

Число бит на char определяется реализацией, определенной CHAR_BIT из заголовка <limits.h>. Это число должно быть 8 или больше. С С++ 03 и ранее гарантия исходила из спецификации этого символа в стандарте C89, который стандарт С++ отметил (в ненормативном разделе, но все еще) как "включен". С С++ 11 и более поздними версиями С++-стандарт, сам по себе, дает гарантию ≥8. На большинстве платформ CHAR_BIT равно 8, но на некоторых, возможно, еще существующих цифровых сигнальных процессорах Texas Instruments, это 16, а другие значения были использованы.

Независимо от значения CHAR_BIT sizeof(char) по определению 1, то есть оно не определено:

С++ 11 §5.3.3/1 (в [expr.sizeof]):

" sizeof(char), sizeof(signed char) и sizeof(unsigned char) равны 1.

То есть, char и его варианты являются основной единицей адресации памяти, которая является основным значением байта, как в общей речи, так и формально в С++:

С++ 11 §1.7/1 (в [intro.memory]):

" Фундаментом памяти в модели памяти С++ является байт.

Это означает, что на вышеупомянутых DSP-типах нет С++-метода получения указателей на отдельные октеты (8-разрядные части). И это, в свою очередь, означает, что код, который должен иметь дело с endianness или другими способами, должен обрабатывать значения char как последовательности октетов, в частности для сетевых коммуникаций, нужно делать вещи с char значениями, которые не имеют смысла в система, где CHAR_BIT равно 8. Это также означает, что обычные строковые литералы С++, если они соответствуют стандарту, и если стандартное программное обеспечение платформы использует 8-битную кодировку символов, будет тратить память.

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

Это иллюстрирует базовое слияние трех аспектов в одном типе С++ char:

  • единица адресации памяти, байт a.k.a.,

  • наименьший базовый тип (было бы хорошо с типом octet) и

  • единица кодировки символов.

И да, это конфликт.


Факты о кодировке UTF-16.

Unicode - это большой набор 21-битных кодовых точек, большинство из которых составляют персонажи сами по себе, но некоторые из них объединены с другими для формирования символов. Например. персонаж с акцентом типа "é" может быть сформирован путем комбинирования кодовых точек для "e" и "" -а-акцента. И так как это общий механизм, это означает, что символ Юникода может быть произвольным числом кодовых точек, хотя обычно он равен обычно.

Кодировка UTF-16 изначально была схемой совместимости для кода на основе исходного Unicode и 16 бит на кодовую точку, когда Unicode был расширен до 21 бит на кодовую точку. Основная схема состоит в том, что кодовые точки в определенных диапазонах исходного Юникода представлены как сами по себе, а каждая новая кодовая точка Юникода представлена ​​в виде суррогатной пары 16-битных значений. Для суррогатных значений пары используется небольшой диапазон исходного Юникода.

В то время примеры программного обеспечения, основанного на 16 бит на кодовую точку, включали 32-битную Windows и язык Java.

В системе с 8-битным байтом UTF-16 является примером кодировки широкоформатного, то есть с блоком кодирования, более широким, чем базовый адресный блок. Затем байтовые ориентированные текстовые кодировки называются узким текстом. В такой системе С++ char соответствует последней, но не первой.

В С++ 03 единственным встроенным типом, подходящим для блока широкоформатного кодирования, был wchar_t.

Тем не менее, стандарт С++ эффективно требует, чтобы wchar_t был подходящим для кодовой точки, что для современного 21-битового кода для Unicode означает, что он должен быть 32 бита. Таким образом, не существует специального типа С++ 03, который соответствует требованиям значений кодировки UTF-16, 16 бит на каждое значение. Из-за исторических причин наиболее распространенная система, основанная на UTF-16 как широком текстовом кодировании, а именно Microsoft Windows, определяет wchar_t как 16 бит, которые после расширения Unicode были вопиющим противоречием со стандартом, но затем стандарт нецелесообразно в отношении этой проблемы. Некоторые платформы определяют wchar_t как 32 бита.

В С++ 11 были введены новые типы char16_t и char32_t, где первая (предназначена для) подходит для значений кодировки UTF-16.


О вопросе.

Что касается вопроса о предполагаемом предположении

"система с кодировкой символов UTF-16

это может означать одну из двух вещей:

  • система с UTF-16 в качестве стандартной узкой кодировки или
  • система с UTF-16 как стандартная широкоформатная кодировка.

С UTF-16 в качестве стандартного узкого кодирования CHAR_BIT ≥ 16 и (по определению) sizeof(char)= 1. Я не знаю ни одной системы, т.е. представляется гипотетической. Тем не менее, это, по-видимому, значение, молчаливо принятое в текущих других ответах.

С UTF-16 в качестве стандартного широкого кодирования, как и в Windows, ситуация сложнее, потому что стандарт С++ не соответствует задаче. Но, чтобы использовать Windows в качестве примера, одна практическая возможность заключается в том, что sizeof(wchar_t)= 2. И нужно просто отметить, что стандарт противоречит существующей практике и практическим соображениям для этой проблемы, когда идеальным является то, что стандарты вместо стандартизации существующих практика, там, где есть.

Теперь, наконец, мы займемся рассмотрением вопроса,

" Есть ли конфликт между этими вышеприведенными инструкциями или является sizeof(char) = 1 просто значением по умолчанию (определение) и будет определяться реализацией зависит от каждой системы?

Это ложная дихотомия. Две возможности не противоположны. Мы имеем

  • В действительности существует конфликт между char как единицей кодирования символов и как блок адресации памяти (байт). Как уже отмечалось, язык Pascal имеет ключевое слово packed для решения одного аспекта этого конфликта, а именно требования хранения и обработки. И существует еще один конфликт между формальными требованиями к wchar_t и его использованием для кодирования UTF-16 в наиболее широко используемой системе, в которой используется кодировка UTF-16, а именно Windows.

  • sizeof(char) = 1 по определению: он не зависит от системы.

  • CHAR_BIT определяется реализацией и гарантируется ≥ 8.

Ответ 3

Нет, нет конфликта. Эти два утверждения относятся к различным определениям байта.

UTF-16 подразумевает, что байт - это то же самое, что и октет - группа из 8 бит.

В языке языка С++ это то же самое, что и char. Нет ограничений на то, сколько бит может содержать бит С++. Количество бит в С++-байте определяется константой макроса CHAR_BIT.

Если ваша реализация на С++ решит использовать 16 бит для представления каждого символа, тогда CHAR_BIT будет 16, и каждый С++-байт займет два UTF-16-байта. sizeof(char) будет по-прежнему 1, и размеры всех объектов будут измеряться в терминах 16-разрядных байтов.

Ответ 4

A char определяется как 1 байт. Байт - это наименьшая адресуемая единица. Это 8 бит в общих системах, но на некоторых системах это 16 бит, или 32 бита, или что-нибудь еще (но должно быть не менее 8 для С++).

Это несколько сбивает с толку, потому что в популярном байте-жаргоне используется то, что технически известно как октет (8 бит).

Итак, ваши вторая и третья цитаты верны. Первая цитата, строго говоря, неверна.

Как определено в [intro.memory]/1 в стандарте С++, char нужно только удержать основной набор символов выполнения, который составляет приблизительно 100 символов (все из которых отображаются в диапазоне 0 - 127 ASCII) и октеты, составляющие кодировку UTF-8. Возможно, это то, что автор имел в виду под машинным набором символов.


В системе, где аппаратное обеспечение является октетом, но набор символов является Unicode, вероятно, что char останется 8-битным. Однако существуют типы char16_t и char32_t (добавлены в С++ 11), которые предназначены для использования в вашем коде вместо char для систем с 16-разрядными или 32-разрядными наборами символов.

Итак, если система идет с char16_t, тогда вы должны использовать std::basic_string<char16_t> вместо std::string и т.д.

Именно то, как обрабатывать UTF-16, будет зависеть от деталей реализации, выбранных системой. Unicode - это 21-битный набор символов, а UTF-16 - многобайтовая кодировка; поэтому система может перейти по пути, подобному Windows, и использовать std::basic_string<char16_t> с кодировкой UTF-16 для строк; или он может пойти для std::basic_string<char32_t> с сырыми кодовыми точками Unicode в качестве символов.

Сообщение Alf более подробно освещает некоторые проблемы, которые могут возникнуть.

Ответ 5

Без цитирования стандарта легко дать просто ответ, потому что:

Определение байта не 8 бит. Байт - это любой размер, но наименьшая адресуемая единица памяти. Чаще всего это 8 бит, но нет оснований не иметь 16-битовый байт.

Стандарт С++ дает больше ограничений, поскольку он должен быть не менее 8 бит.

Таким образом, нет проблемы с sizeof (char) всегда 1, независимо от того, что. Иногда он будет стоять как 8 бит, иногда 16 бит и так далее.