На каких платформах есть что-то, кроме 8-битного символа?

Время от времени кто-то из SO указывает, что char (aka ‘byte’) не обязательно 8 бит .

Кажется, что 8-битный char почти универсален. Я бы подумал, что для основных платформ необходимо иметь 8-битный char чтобы обеспечить его жизнеспособность на рынке.

Как сейчас, так и исторически, какие платформы используют char который не является 8 битами, и почему они отличаются от «обычных» 8 бит?

Когда вы пишете код и думаете о межплатформенной поддержке (например, для библиотек общего пользования), какое внимание следует уделить платформам с не-8-битным char ?

Раньше я сталкивался с некоторыми процессорами Analog Devices DSP, для которых char имеет 16 бит. Я полагаю, что DSP – это немного нишевая архитектура. (Опять же, в то время, когда ручной ассемблер легко избил то, что могли сделать доступные компиляторы C, поэтому на этой платформе я действительно не получал большой опыт работы с C).

char также 16 бит на процессорах Texas Instruments C54x, которые появились, например, в OMAP2. Существуют и другие DSP с 16 и 32-разрядным char . Я думаю, что даже слышал о 24-битном DSP, но я не могу вспомнить, что, возможно, я себе это представлял.

Другое соображение заключается в том, что POSIX имеет мандат CHAR_BIT == 8 . Поэтому, если вы используете POSIX, вы можете предположить это. Если кому-то позже нужно будет перенести ваш код на почти реализацию POSIX, у вас просто есть функции, которые вы используете, а на другой размер, это их неудача.

В целом, однако, я думаю, что почти всегда легче обойти проблему, чем думать об этом. Просто введите CHAR_BIT . Если вам нужен точный 8-битный тип, используйте int8_t . Ваш код будет неудобно компилировать на реализациях, которые не предоставляют один, вместо того, чтобы молча использовать размер, которого вы не ожидали. По крайней мере, если я ударил случай, когда у меня были веские основания предполагать это, я бы это утвердил.

Когда вы пишете код и думаете о межплатформенной поддержке (например, для библиотек общего пользования), какое внимание следует уделить платформам с не-8-битным символом?

Это не так много, что «стоит уделить внимание» чему-то, поскольку он играет по правилам. В C ++, например, стандарт говорит, что все байты будут иметь «по крайней мере» 8 бит. Если ваш код предполагает, что байты имеют ровно 8 бит, вы нарушаете стандарт.

Теперь это может показаться глупым – « Конечно, у всех байтов 8 бит!», Я слышал, вы говорите. Но многие очень умные люди полагались на предположения, которые не были гарантией, а затем все сломалось. История изобилует такими примерами.

Например, большинство разработчиков за 90-е годы предположили, что конкретная временная задержка без использования процессора с фиксированным числом циклов займет фиксированное количество часов, потому что большинство потребительских процессоров были примерно эквивалентными по мощности. К сожалению, компьютеры быстро развивались быстрее. Это породило появление ящиков с кнопками «Turbo», цель которых, по иронии судьбы, заключалась в том, чтобы замедлить работу компьютера, чтобы игры с использованием техники задержки времени могли воспроизводиться с разумной скоростью.


Один комментатор спросил, где в стандарте говорится, что символ должен иметь не менее 8 бит. Он находится в разделе 5.2.4.2.1 . Этот раздел определяет CHAR_BIT , количество бит в наименьшем адресуемом объекте и имеет значение по умолчанию 8. Оно также говорит:

Их значения, определяемые реализацией, должны быть равны или больше по величине (по абсолютной величине) тем, которые показаны, с тем же знаком.

Таким образом, любое число, равное 8 или выше, подходит для замещения реализацией в CHAR_BIT .

Машины с 36-разрядными архитектурами имеют 9-битные байты. Согласно Википедии, машины с 36-разрядными архитектурами include в себя:

  • Digital Equipment Corporation PDP-6/10
  • IBM 701/704/709/7090/7094
  • UNIVAC 1103 / 1103A / 1105/1100/2200,

Несколько из которых я знаю:

  • 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 вместо

Нет такой вещи, как полностью переносимый код. 🙂

Да, могут быть разные размеры байтов / символов. Да, могут быть реализации C / C ++ для платформ с очень необычными значениями CHAR_BIT и UCHAR_MAX . Да, иногда можно писать код, который не зависит от размера символа.

Однако практически любой реальный код не является автономным. Например, вы можете писать код, который отправляет двоичные сообщения в сеть (протокол не важен). Вы можете определить структуры, содержащие необходимые поля. Чем вам придется сериализовать его. Просто двоичное копирование структуры в выходной буфер не переносится: обычно вы не знаете ни байтового порядка для платформы, ни выравнивания элементов структуры, поэтому структура просто хранит данные, но не описывает способ, которым данные должны быть сериализованы ,

ОК. Вы можете выполнять преобразования порядка байтов и перемещать элементы структуры (например, uint32_t или аналогичные), используя memcpy в буфер. Почему memcpy ? Поскольку существует множество платформ, где невозможно записать 32-разрядную (16-разрядную, 64-разрядную – без разницы), когда целевой адрес не будет правильно выровнен.

Итак, вы уже много сделали для достижения переносимости.

И вот последний вопрос. У нас есть буфер. Данные из него отправляются в сеть TCP / IP. Такая сеть предполагает 8-битные байты. Вопрос в том, какой тип буфера должен быть? Если ваши символы 9-бит? Если они 16-битные? 24? Может быть, каждый символ соответствует одному 8-битовому байту, отправленному в сеть, и используется только 8 бит? Или, может быть, несколько сетевых байтов упакованы в 24/16/9-битные символы? Это вопрос, и трудно поверить, что есть один ответ, который подходит для всех случаев. Многое зависит от реализации сокета для целевой платформы.

Итак, о чем я говорю. Обычно код может быть сравнительно легко переносимым в определенной степени . Это очень важно сделать, если вы ожидаете использовать код на разных платформах. Тем не менее, улучшение переносимости за пределами этой меры – это то, что требует больших усилий и часто дает мало , так как реальный код почти всегда зависит от другого кода (реализация сокета в примере выше). Я уверен, что примерно 90% возможностей кода работать на платформах с байтами, отличными от 8-бит, почти бесполезно, поскольку для него используется среда, привязанная к 8-разрядной. Просто проверьте размер байта и выполните утверждение времени компиляции. Вам почти наверняка придется переписать много для очень необычной платформы.

Но если ваш код очень «автономный» – почему бы и нет? Вы можете написать его таким образом, чтобы разрешать разные размеры байтов.

Похоже, что вы все еще можете купить IM6100 (т. Е. PDP-8 на чипе) со склада. Это 12-битная архитектура.

Многие чипы DSP имеют 16- или 32-битный char . Например, TI делает такие чипы, например .

Языки программирования C и C ++, например, определяют байт как «адресную единицу данных, достаточно большую, чтобы содержать любой элемент базового набора символов среды исполнения» (раздел 3.6 стандарта C). Поскольку тип данных интеграла C char должен содержать не менее 8 бит (раздел 5.2.4.2.1), байт в C по меньшей мере способен удерживать 256 различных значений. Различные реализации C и C ++ определяют байты как 8, 9, 16, 32 или 36 бит

Цитируется по адресу http://en.wikipedia.org/wiki/Byte#History

Не уверен в других языках.

http://en.wikipedia.org/wiki/IBM_7030_Stretch#Data_Formats

Определяет байт на этой машине переменной длины

В семействе DEC PDP-8 было 12-битное слово, хотя обычно вы использовали 8 бит ASCII для вывода (в основном в Teletype). Однако был также код символа 6-BIT, который позволял вам кодировать 2 символа в одном 12-битном слове.

Например, символы Unicode длиннее 8 бит. Как упоминалось ранее, спецификация C определяет типы данных по их минимальным размерам. Используйте sizeof и значения в limits.h если вы хотите опросить свои типы данных и узнать, какой размер они предназначены для вашей конфигурации и архитектуры.

По этой причине я стараюсь придерживаться типов данных, таких как uint16_t когда мне нужен тип данных определенной длины бит.

Изменить: Извините, я изначально неправильно понял ваш вопрос.

Спектр C говорит, что объект char «достаточно велик для хранения любого члена набора символов выполнения». limits.h указывает минимальный размер 8 бит, но определение оставляет максимальный размер открытого char .

Таким образом, 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 .

Какое внимание следует уделить платформам с не-8-битным символом?

магические числа появляются, например, при смене;

большинство из них можно обрабатывать довольно просто, используя 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 …

есть такие вещи, которые нужно соблюдать, хотя в вашем коде нет «волшебных чисел» …

надеюсь, это имеет смысл 🙂

ints – 16 бит (pdp11 и т. д.). Переход к 32-битным архитектурам был трудным. Люди становятся лучше: вряд ли кто-то предполагает, что указатель поместится долго (вы не правы?). Или смещения файлов, или временные метки, или …

8-битные символы уже являются анахронизмом. Нам уже нужно 32 бита для хранения всех наборов символов в мире.

  • Как работает Codename One?
  • Кросс-платформенный формат строки для переменных типа size_t?
  • Запуск SWT на основе кросс-платформенной банки на Mac
  • Автоматически добавлять все файлы в папку к цели с помощью CMake?
  • Interesting Posts

    img src SVG изменение цвета заливки

    Список только каталогов, использующих ls в bash: экзамен

    Можно ли заставить CMake создавать статическую и общую версию одной и той же библиотеки?

    Как создать собственный атрибут проверки для MVC

    Цветная ячейка, основанная на текстовом значении

    Почему при использовании шаблонов я получаю ошибки «неразрешенных внешних символов»?

    Не удается расширить (раздел C :)

    Использование .Net 4.5 Функция Async для программирования сокетов

    Получить первый URL-адрес поиска google для выделенного текста в любом приложении

    Чтение 40-гигабайтного CSV-файла в R с использованием bigmemory

    NoClassDefFoundError, когда GoogleAnalyticsTracker.getInstance ()

    Маршрутизатор для настройки маршрутизатора отлично работает с прямым кабелем до 2-3 метров, он не работает на 45 метров, почему?

    используя $ slice operator для получения последнего элемента массива в mongodb

    Что делает java: comp / env / do?

    отключить nganimate для некоторых элементов

    Давайте будем гением компьютера.