Около десяти лет назад нам пришлось портировать нашу встроенную базу данных C на процессор DSP, который оказался главным процессором автомобильной стереосистемы. В худшем случае это была 24-битная машина: sizeof(char) == sizeof(int) == sizeof(void*) == 1
, что составляло 24 бита. Мы назвали ветвь, которая имела дело с этим портом "24-битный ад".
С тех пор мы портировали нашу библиотеку на многие платформы, но ни одна из них не была такой странной. Они все еще могут существовать (дешевые 24-битные DSP-чипы теперь стали еще дешевле), которые можно найти в недорогих устройствах, где простота программирования является отдаленной секундой после низкой спецификации материалов (BOM). Если подумать, я думаю, что мы столкнулись с машиной, в которой смещение вправо от целого числа без знака не обязательно вставляет нулевые биты. Тем не менее, крайне нестандартные арифметические правила для платформы гарантируют сложный, подверженный ошибкам перенос программного обеспечения на нее, что значительно увеличивает затраты на разработку программного обеспечения. В какой-то момент преобладает здравомыслие и соблюдаются стандарты.
Я подозреваю, что причиной появления этих правил в C99 является их присутствие в C89 и более ранние итерации языка. Не забывайте, что когда C был изобретен, компьютеры были намного разнообразнее, чем сегодня. Были доступны процессоры с разделением по битам, где вы могли добавить столько бит, сколько захотите, просто добавив микросхемы. А до C вам приходилось кодировать на ассемблере или беспокоиться о том, где именно в ОЗУ будет находиться ваш код и т. Д.
C был значительным шагом вперед с точки зрения переносимости, но он должен был охватывать разнообразные системы, отсюда и самые общие правила. Спустя 20 лет, когда появилась Java, она имела историческое преимущество, позволяя ей заранее объявлять, какими должны быть большие примитивные типы, что делает все намного проще, если выбор Java является здравым.
Я знаю, что вы в основном спрашиваете о целых числах, но я столкнулся с некоторыми странностями, когда дело доходит до указателей. Ранние компьютеры Macintosh имели 32-битные процессоры (Motorola 68000), но только 24-битные шины памяти. Таким образом, 0x00123456 и 0xFF123456 ссылаются на одну и ту же ячейку памяти, поскольку процессор обрезает верхние 8 бит при обращении к ОЗУ. Инженеры Apple использовали эти биты для хранения метаданных о памяти, на которую указывал указатель. Таким образом, при сравнении указателей нужно было сначала маскировать верхние биты. И не начинайте меня с архитектуры сегментированной памяти x86. :)
Поскольку мы занимаемся этой темой, взглянем на стандарт кодирования MISRA , который предпочитают производители автомобилей, которым требуется максимальная мобильность и безопасность. Также посмотрите на Восторг Хакера Генри С. Уоррена, в котором есть тонны полезных хитростей.