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

Почему sizeof встроенных типов, кроме char, зависит от компилятора в C & С++?

Почему фундаментальные типы в C и С++ строго не определены, как в Java, где int всегда 4 байта, а long - 8 байт и т.д. Насколько мне известно, на C и С++ определен только a char как 1 байт, и все остальное определяется по-разному разными компиляторами. Таким образом, int в C и С++ не обязательно должен быть 4 байта, если он длиннее, чем short и short длиннее char.
Я просто задавался вопросом, почему это так, и это служит какой-либо цели?

4b9b3361

Ответ 1

Причина в значительной степени связана с тем, что C переносится на гораздо более широкий спектр платформ. Существует много причин, по которым разные типы данных оказались разными по размерам на разных платформах, но, по крайней мере, исторически, int был адаптирован к размеру родного слова платформы. На PDP-11 это было 16 бит (и long изначально было изобретен для 32-битных чисел), тогда как некоторые встроенные компиляторы платформы даже имеют 8-бит int s. Когда появились 32-битные платформы и начали иметь 32-разрядные int s, был изобретен short для представления 16-разрядных чисел.

В настоящее время большинство 64-разрядных архитектур используют 32-разрядный int просто для совместимости с большой базой программ на C, которые первоначально были написаны для 32-разрядных платформ, но были 64-битные компиляторы C с 64- бит int, в том числе некоторые ранние платформы Cray.

Кроме того, в ранние дни вычислений форматы и размеры с плавающей запятой, как правило, были значительно менее стандартизированы (IEEE 754 не появлялся до 1985 года), поэтому float и double чем целые типы данных. Обычно они даже не предполагают наличия таких особенностей, как бесконечности, NaNs или подписанные нули.

Кроме того, следует сказать, что a char не определен как 1 байт, а скорее для любого sizeof возвращает 1 для. Это не обязательно 8 бит. (Для полноты, возможно, здесь должно быть добавлено, что " byte", поскольку термин не определяется универсально как 8 бит; было много исторических определений, и в контексте стандарта ANSI C "байтом" на самом деле определяется как наименьшая единица хранения, которая может хранить char, независимо от характера char.)

Существуют также такие архитектуры, как 36-разрядные PDP-10 и 18-разрядные PDP-7, которые также запускают программы C. В наши дни они могут быть довольно редкими, но помогают объяснить, почему типы данных C не определены в терминах 8-битных единиц.

Является ли это, в конце концов, действительно делает язык "более переносимым", чем, возможно, обсуждаются языки, такие как Java, но он был бы субоптимальным для запуска программ Java на 16-разрядных процессорах и довольно странно на 36- разрядных процессоров. Возможно, справедливо сказать, что он делает язык более портативным, но программы, написанные в нем, менее портативны.

EDIT: В ответ на некоторые комментарии я просто хочу добавить в качестве фрагмента мнения, что C как язык отличается от языков, таких как Java/Haskell/ADA, которые являются более или "не принадлежащих" корпорацией или органом по стандартизации. Есть ANSI C, конечно, но C больше, чем ANSI C; это живое сообщество, и есть много реализаций, которые не совместимы с ANSI, но, тем не менее, являются "C". Утверждая, что реализации, использующие 8-разрядные int, C, аналогичны утверждению, является ли шотландский язык английским, поскольку он в основном бессмыслен. Они используют 8-бит ints по уважительным причинам, никто, кто знает C достаточно хорошо, не сможет рассуждать о программах, написанных для таких компиляторов, и любой, кто пишет программы C для таких архитектур, хотел бы, чтобы их int составляли 8 бит.

Ответ 2

Интегральные типы данных строго не определены, поэтому компилятор может выбрать наиболее эффективные для целевого оборудования. Однако существуют некоторые гарантии минимальных размеров каждого типа (например, int составляет не менее 16 бит).

Посмотрите эту страницу: http://en.cppreference.com/w/cpp/language/types

Ответ 3

Эффективность является частью ответа - например, если вы используете C или С++ на машине, использующей 36-разрядные регистры, вы не хотите, чтобы каждая операция включала служебные данные для маскировки результатов, чтобы они выглядели/действуют как 32 бита.

Это действительно только часть ответа. Другая часть состоит в том, что C и С++ были (и) предназначены для системных языков программирования. Вы намерены писать с ними такие вещи, как виртуальные машины и операционные системы.

Это означает, что если (например) вы пишете код, который будет взаимодействовать с MMU на этой 36-битной машине, и вам нужно установить бит 34 некоторого определенного слова, основной смысл с C и С++ заключается в том, что вы должны иметь возможность сделать это прямо на языке. Если язык начинается с того, что указывается, что ни один 36-битный тип не может существовать в первую очередь, это обычно затрудняет прямое управление 36-битным типом на этом языке.

Итак, одно из основных предпосылок C и С++ состоит в том, что если вам нужно что-то сделать, вы должны иметь возможность сделать что-то внутри языка. Соответствующая предпосылка на Java была почти противоположной: что то, что она позволяла вам делать, должно быть ограничено теми операциями, которые она могла бы гарантировать, была бы безопасной.

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

Конечно, ситуация изменилась - апплеты больше не являются главной целью для Java в большинстве людей. Хуже того, безопасность, на которую они нацелились, была несколько неуловимой целью, поэтому многие люди рекомендуют отключать Java в вашем веб-браузере. Тем не менее, большинство ограничений, предназначенных для поддержки этой модели, остаются на месте.

Вероятно, я должен добавить, что это не совсем и то, и другое. Существует несколько способов обеспечения некоторой средней позиции. Разумно недавние итерации как стандартов C, так и С++ включают типы, которые int32_t. Это гарантирует 32-битное представление с двумя дополнениями, примерно так же, как тип Java.

Конечно, это не единственный возможный способ сделать примерно то же самое. Ада, например, занимает несколько иной путь. Вместо того, чтобы "родные" типы ориентировались на машину, а затем добавляли специальные типы с гарантированными свойствами, они шли в другом направлении и имели собственные типы с гарантированными свойствами, но также и целый объект для определения нового типа, который соответствовал непосредственно целевой машины. Однако, к лучшему или к худшему, Ada никогда не достигала почти такого широкого использования, как C, С++ или Java, и ее подход к этой конкретной проблеме, похоже, не был принят и на многих других языках.