Почему потоки C ++ используют char вместо unsigned char? - PullRequest
50 голосов
/ 10 ноября 2008

Мне всегда было интересно, почему библиотека C ++ Standard создала экземпляр потока basic_ [io] и всех его вариантов, используя тип char вместо типа unsigned char. char означает (в зависимости от того, подписано оно или нет), вы можете иметь переполнение и недостаточное значение для таких операций, как get (), что приведет к определенному для реализации значению задействованных переменных. Другой пример - когда вы хотите вывести неформатированный байт в ostream, используя его функцию put.

Есть идеи?


Примечание : Я все еще не совсем уверен. Поэтому, если вы знаете точный ответ, вы все равно можете опубликовать его.

Ответы [ 4 ]

24 голосов
/ 10 ноября 2008

Возможно, я неправильно понял вопрос, но преобразование из unsigned char в char не является неопределенным, оно зависит от реализации (4.7-3 в стандарте C ++).

Тип однобайтового символа в C ++ - "char", а не "unsigned char". Это дает реализациям немного больше свободы для достижения наилучших результатов на платформе (например, орган по стандартизации, возможно, полагал, что существуют процессоры, в которых арифметика со знаком байтов быстрее, чем арифметика без знака, хотя это предположение с моей стороны). Также для совместимости с C. Результатом удаления этого вида неопределенности неопределенности из C ++ является C #; -)

Учитывая, что тип "char" существует, я думаю, что обычные потоки имеют смысл использовать его, даже если его подпись не определена. Поэтому, возможно, на ваш вопрос отвечает ответ «почему C ++ просто не определил char как unsigned?»

15 голосов
/ 27 мая 2010

Я всегда понимал это так: цель класса iostream состоит в том, чтобы читать и / или записывать поток символов, которые, если вы об этом думаете, являются абстрактными сущностями, которые представлены только компьютером, использующим кодировка символов. Стандарт C ++ прилагает большие усилия, чтобы избежать закрепления кодировки символов, говоря только о том, что «объекты, объявленные как символы (char), должны быть достаточно большими, чтобы хранить любой элемент базового набора символов реализации», потому что ему не нужно заставить "базовый набор символов реализации" определять язык C ++; стандарт может оставить решение , какое кодирование символов используется для реализации (компилятор вместе с реализацией STL), и просто отметить, что char объекты представляют отдельные символы в некоторой кодировке.

Автор реализации может выбрать однооктетную кодировку, такую ​​как ISO-8859-1 или даже двухоктетную кодировку, такую ​​как UCS-2 . Это не важно Пока объект char «достаточно большой, чтобы хранить любой элемент базового набора символов реализации» (обратите внимание, что это явно запрещает кодировки переменной длины ), тогда реализация может даже выбрать кодировку, которая представляет базовую латиницу таким образом, который несовместим с любой обычной кодировкой!

Заблуждение вызывает то, что типы char, signed char и unsigned char имеют в своих именах "char", но важно помнить, что char не принадлежит к тому же семейству фундаментальных типы как signed char и unsigned char. signed char входит в семейство целочисленных типов со знаком:

Существует четыре целочисленных типа со знаком : "знаковый символ", "короткое целое", "int" и "длинное целое".

и unsigned char входят в семейство целочисленных типов без знака:

Для каждого из целочисленных типов со знаком существует соответствующий (но различный) целочисленный тип без знака : "unsigned char", "unsigned short int", "unsigned int" и "unsigned long int , "...

Единственное сходство между типами char, signed char и unsigned char заключается в том, что «[они] занимают одинаковое количество памяти и имеют одинаковые требования к выравниванию». Таким образом, вы можете reinterpret_cast от char * до unsigned char *, чтобы определить числовое значение символа в наборе символов выполнения.

Чтобы ответить на ваш вопрос, причина, по которой STL использует char в качестве типа по умолчанию, заключается в том, что стандартные потоки предназначены для чтения и / или записи потоков символов, представленных char объектами, а не целыми числами (signed char и unsigned char). Использование char в сравнении с числовым значением является способом разделения проблем.

4 голосов
/ 10 ноября 2008

char - для символов, unsigned char для необработанных байтов данных и подписанных символов для, ну, в общем, подписанных данных.

Стандарт не указывает, будет ли использоваться char со знаком или без знака для реализации char - это зависит от компилятора. Он только указывает, что «char» будет «достаточно» для хранения символов в вашей системе - так, как символы были в те дни, то есть без UNICODE.

Использование символа "char" для символов является стандартным способом. Использование unsigned char - это хак, хотя оно будет соответствовать реализации char компилятором на большинстве платформ.

0 голосов
/ 20 мая 2012

Я думаю этот комментарий это хорошо объясняет. Цитировать:

Знаковый char и unsigned char являются арифметическими, целочисленными типами, такими же, как int и unsigned int. С другой стороны, char явно предназначен для типа «I / O», который представляет собой непрозрачную, специфичную для системы фундаментальную единицу данных на вашей платформе. Я бы использовал их в этом духе.

...