На каких платформах есть что-то отличное от 8-битного char?
Время от времени кто-то из SO указывает, что char
(aka 'byte') не обязательно 8 бит.
Кажется, что 8-бит char
является почти универсальным. Я бы подумал, что для основных платформ необходимо иметь 8-разрядный char
, чтобы обеспечить его жизнеспособность на рынке.
Как сейчас, так и исторически, какие платформы используют char
, который не является 8 битами, и почему они отличаются от "обычных" 8 бит?
При написании кода и понимании кросс-платформенной поддержки (например, для общедоступных библиотек), какое внимание следует уделить платформам с не-8-разрядными char
?
В прошлом я сталкивался с некоторыми процессорами Analog Devices DSP, для которых char
- 16 бит. Я полагаю, что DSP - это немного нишевая архитектура. (Опять же, в то время, когда ручной ассемблер легко бил то, что могли сделать доступные компиляторы C, поэтому на этой платформе я действительно не получал много опыта.)
Ответы
Ответ 1
char
также 16 бит на процессорах Texas Instruments C54x, которые появились, например, в OMAP2. Существуют и другие DSP с 16 и 32 бит char
. Я думаю, что даже слышал о 24-битном DSP, но я не могу вспомнить, что, возможно, я себе это представлял.
Еще одно соображение заключается в том, что POSIX имеет мандат CHAR_BIT == 8
. Поэтому, если вы используете POSIX, вы можете предположить это. Если кому-то позже нужно будет перенести свой код на почти реализацию POSIX, просто так получится, что у вас есть функции, которые вы используете, но с другим размером char
, что их неудача.
В общем, я думаю, что почти всегда легче обойти проблему, чем думать об этом. Просто введите CHAR_BIT
. Если вам нужен точный 8-разрядный тип, используйте int8_t
. Ваш код будет неудобно компилировать на реализациях, которые не предоставляют один, вместо того, чтобы молча использовать размер, которого вы не ожидали. По крайней мере, если я ударил случай, когда у меня были все основания предполагать это, я бы это сказал.
Ответ 2
При написании кода и понимании кросс-платформенной поддержки (например, для общедоступных библиотек), какое внимание следует уделять платформам с не-8-разрядными char?
Это не так много, что "стоит уделить внимание" чему-то, поскольку он играет по правилам. В С++, например, стандарт говорит, что все байты будут иметь "по крайней мере" 8 бит. Если ваш код предполагает, что байты имеют ровно 8 бит, вы нарушаете стандарт.
Теперь это может показаться глупым - "конечно, все байты имеют 8 бит!", я слышу, как вы говорите. Но многие очень умные люди полагались на предположения, которые не были гарантией, а затем все сломалось. История изобилует такими примерами.
Например, большинство разработчиков в начале 90-х годов предположили, что конкретная временная задержка без использования процессора с фиксированным числом циклов займет фиксированное количество часов, потому что большинство потребительских процессоров были примерно эквивалентными по мощности. К сожалению, компьютеры быстро развивались быстрее. Это породило появление ящиков с кнопками "Turbo", цель которых, по иронии судьбы, заключалась в том, чтобы замедлить работу компьютера, чтобы игры с использованием техники задержки времени могли воспроизводиться с разумной скоростью.
Один комментатор спросил, где в стандарте говорится, что char должен иметь не менее 8 бит. Это в разделе 5.2.4.2.1. В этом разделе определяется CHAR_BIT
, количество бит в наименьшем адресуемом объекте и имеет значение по умолчанию 8. Оно также говорит:
Их значения, определяемые реализацией, должны быть равны или больше по величине (по абсолютной величине) тем, которые показаны, с тем же знаком.
Поэтому любое число, равное 8 или выше, подходит для подстановки реализацией в CHAR_BIT
.
Ответ 3
Машины с 36-разрядными архитектурами имеют 9-битные байты. Согласно Wikipedia, машины с 36-разрядными архитектурами включают в себя:
- Digital Equipment Corporation PDP-6/10
- IBM 701/704/709/7090/7094
- UNIVAC 1103/1103A/1105/1100/2200,
Ответ 4
Несколько из которых я знаю:
- DEC PDP-10: переменная, но чаще всего 7-битные символы упакованы по 5 на 36-битное слово или 9 бит, 4 слова на слово
- Контрольные данные: мейнфреймы (CDC-6400, 6500, 6600, 7600, Cyber 170, Cyber 176 и т.д.) 6-битные символы, упакованные 10 на 60-битное слово.
- Универсальные мэйнфреймы Unisys: 9 бит/байт
- Windows CE: просто не поддерживает тип ` char` вообще - требуется 16-бит wchar_t вместо
Ответ 5
Нет такой вещи, как полностью переносимый код.: -)
Да, могут быть разные размеры байтов / char. Да, могут быть реализации C/С++ для платформ с очень необычными значениями CHAR_BIT
и UCHAR_MAX
. Да, иногда можно писать код, который не зависит от размера char.
Однако практически любой реальный код не является автономным. Например. вы можете написать код, который отправляет двоичные сообщения в сеть (протокол не важен). Вы можете определить структуры, содержащие необходимые поля. Чем вам придется сериализовать его. Просто двоичное копирование структуры в выходной буфер не переносится: обычно вы не знаете ни байтового порядка для платформы, ни выравнивания элементов структуры, поэтому структура просто хранит данные, но не описывает способ, которым данные должны быть сериализованы.
Ok. Вы можете выполнять преобразования порядка байтов и перемещать элементы структуры (например, uint32_t
или аналогичные) с помощью memcpy
в буфер. Почему memcpy
? Поскольку существует множество платформ, где невозможно записать 32-разрядную (16-разрядную, 64-разрядную - без разницы), когда целевой адрес не выровнен правильно.
Итак, вы уже много сделали для достижения переносимости.
И вот последний вопрос. У нас есть буфер. Данные из него отправляются в сеть TCP/IP. Такая сеть предполагает 8-битные байты. Вопрос в том, какой тип буфера должен быть? Если ваши символы 9-бит? Если они 16-битные? 24? Может быть, каждый char соответствует одному 8-битовому байту, отправленному в сеть, и используется только 8 бит? Или, может быть, несколько сетевых байтов упакованы в 24/16/9-битные символы? Это вопрос, и трудно поверить, что есть один ответ, который подходит для всех случаев. Многое зависит от реализации сокета для целевой платформы.
Итак, о чем я говорю. Обычно код может быть относительно легко сделан переносимым в определенной степени. Это очень важно сделать, если вы ожидаете использовать код на разных платформах. Тем не менее, улучшая переносимость за пределами этой меры - это вещь, которая требует больших усилий и часто дает мало, поскольку реальный код почти всегда зависит от другого кода (реализация сокета в примере выше). Я уверен, что примерно 90% возможностей кода работать на платформах с байтами, отличными от 8-бит, почти бесполезно, поскольку для него используется среда, привязанная к 8-разрядной. Просто проверьте размер байта и выполните утверждение времени компиляции. Вам почти наверняка придется переписать много для очень необычной платформы.
Но если ваш код очень "автономный" - почему бы и нет? Вы можете записать его таким образом, чтобы разрешить различные размеры байтов.
Ответ 6
Похоже, вы все еще можете купить IM6100 (т.е. PDP-8 на чипе) со склада. Это 12-битная архитектура.
Ответ 7
Многие чипы DSP имеют 16- или 32-разрядный char
. TI обычно делает такие микросхемы например.
Ответ 8
Языки программирования C и С++, например, определяют байт как "адресную единицу данных, достаточно большую для того, чтобы содержать любой элемент базового набора символов среды исполнения" (раздел 3.6 стандарта C). Поскольку интегральный тип данных C char должен содержать не менее 8 бит (раздел 5.2.4.2.1), байт в C по меньшей мере способен удерживать 256 различных значений. Различные реализации C и С++ определяют байты как 8, 9, 16, 32 или 36 бит
Цитата из http://en.wikipedia.org/wiki/Byte#History
Не уверен в других языках.
http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats
Определяет байт на этой машине переменной длины
Ответ 9
В семействе DEC PDP-8 было 12-битное слово, хотя вы обычно использовали 8 бит ASCII для вывода (в основном в Teletype). Однако был также код символа 6-BIT, который позволял вам кодировать 2 символа в одном 12-битном слове.
Ответ 10
Для одного, символы Unicode длиннее 8 бит. Как упоминалось ранее, спецификация C определяет типы данных по их минимальным размерам. Используйте sizeof
и значения в limits.h
, если вы хотите опросить свои типы данных и точно узнать, какой размер они предназначены для вашей конфигурации и архитектуры.
По этой причине я пытаюсь придерживаться типов данных, таких как uint16_t
, когда мне нужен тип данных определенной длины бит.
Изменить: Извините, я изначально неправильно понял ваш вопрос.
C spec говорит, что объект char
"достаточно велик, чтобы хранить любой член набора символов выполнения". limits.h
отображает минимальный размер 8 бит, но определение оставляет максимальный размер a char
открытым.
Таким образом, a char
, по крайней мере, до тех пор, пока наибольший символ из вашего набора выполнения архитектуры (обычно округляется до ближайшей 8-битной границы). Если ваша архитектура имеет более длинные коды операций, размер char
может быть длиннее.
Исторически, код операции платформы x86 был длиной в один байт, поэтому char
был первоначально 8-битным значением. Текущие платформы x86 поддерживают коды операций длиннее одного байта, но char
хранится в 8 бит в длину, так как программисты (и большие объемы существующего кода x86) обусловлены.
Если вы думаете о поддержке нескольких платформ, используйте типы, определенные в stdint.h
. Если вы используете (например) uint16_t, то можете быть уверены, что это значение представляет собой неподписанное 16-битное значение для любой архитектуры, независимо от того, соответствует ли это 16-разрядное значение char
, short
, int
, или что-то другое. Большая часть тяжелой работы уже была выполнена людьми, которые написали ваши компиляторы/стандартные библиотеки.
Если вам нужно знать точный размер char
, потому что вы выполняете некоторую низкоуровневую аппаратную манипуляцию, которая его требует, я обычно использую тип данных, который достаточно велик для хранения char
на всех поддерживаемых платформах (обычно достаточно 16 бит) и запускать значение через процедуру convert_to_machine_char
, когда мне нужно точное представление машины. Таким образом, код, специфичный для платформы, ограничен функцией интерфейса, и большую часть времени я могу использовать обычный uint16_t
.
Ответ 11
какое вознаграждение стоит уделять платформам с не-8-разрядным char?
появляются магические числа, например. при сдвиге;
большинство из них можно обрабатывать довольно просто
используя CHAR_BIT и, например, UCHAR_MAX вместо 8 и 255 (или аналогичных).
надеюсь, что ваша реализация определяет такие:)
это "общие" проблемы.....
Другая косвенная проблема: у вас есть:
struct xyz {
uchar baz;
uchar blah;
uchar buzz;
}
это может "только" взять (лучший случай) 24 бита на одной платформе,
но может принимать, например. 72 бита в другом месте.....
если каждый ухар удерживал "бит-флаги", и каждый учар имел только 2 "значительных" бита или флага, которые
вы в настоящее время используете, и вы только организовали их в 3 uchars для "ясности",
то он может быть относительно "более расточительным", например. на платформе с 24-битными школами.....
ничто битовое поле не может решить, но у них есть другие вещи, чтобы следить
для....
в этом случае, только одно перечисление может быть способом получить "самый маленький",
которое вам действительно нужно....
возможно, не настоящий пример, но материал вроде этого "бит" меня при портировании/воспроизведении с некоторым кодом.....
просто тот факт, что если учарь в три раза больше, чем ожидаемый "нормально",
100 таких структур могут потерять много памяти на некоторых платформах.....
где "нормально" это не большая сделка.....
поэтому все может быть "сломанным" или в этом случае "очень быстро удаляет много памяти" из-за
к предположению, что uchar "не очень расточительно" на одной платформе, по сравнению с доступной ОЗУ, чем на другой платформе.....
проблема может быть более заметной, например. для ints также, или других типов,
например у вас есть структура, которая требует 15 бит, поэтому вы вставляете ее в int,
но на какой-то другой платформе int составляет 48 бит или что-то еще.....
"обычно" вы можете разбить его на 2 uchars, но, например, с 24-битным учхом
вам понадобится только один...
поэтому переименование может быть лучшим "общим" решением....
зависит от того, как вы получаете доступ к этим битам:)
Таким образом, могут быть "дефекты дизайна", которые выходят за голову.
даже если код может работать/работать нормально, независимо от того,
размер uchar или uint...
есть такие вещи, на которые нужно следить, хотя там
в вашем коде нет "волшебных чисел"...
надеюсь, что это имеет смысл:)
Ответ 12
ints используется как 16 бит (pdp11 и т.д.). Переход к 32-битным архитектурам был трудным. Люди становятся лучше: вряд ли кто-то предполагает, что указатель поместится долго (вы не правы?). Или смещения файлов, или временные метки, или...
8-битные символы уже являются анахронизмом. Нам уже нужны 32 бита для хранения всех наборов символов мира.