Каков исторический контекст для long и int, которые часто имеют одинаковый размер?

Согласно многочисленным ответам здесь, long и int имеют размер 32 бита на распространенных платформах в C и C++ (Windows & Linux, 32 и 64 бит.) (Я знаю, что стандарта нет, но на практике это наблюдаемые размеры.)

Итак, мой вопрос: как это произошло? Почему у нас есть два типа одного размера? Раньше я всегда предполагал, что long большую часть времени будет 64-битным, а int 32-битным. Я не говорю, что это «должно» быть так или иначе, мне просто любопытно, как мы сюда попали.


person davidtbernal    schedule 17.06.2011    source источник
comment
По моему опыту работы с GCC, sizeof(int) возвращает 4, а sizeof(long) возвращает 8...   -  person zellio    schedule 17.06.2011
comment
на самом деле это открытый вопрос в спецификации, пока сохраняется неравенство, которое я имею в своем ответе.   -  person Charlie Martin    schedule 17.06.2011
comment
Википедия поясняет, что - 64-битные реализации UNIX типа long имеют длину 8 байт.   -  person Chowlett    schedule 17.06.2011


Ответы (5)


Из обоснования C99 (PDF) в разделе 6.2.5:

[...] В 1970-х годах 16-битный C (для PDP-11) впервые представлял информацию о файле с 16-битными целыми числами, которые быстро устарели с прогрессом дисков. Люди перешли на 32-битную файловую систему, сначала используя конструкции int[2], которые были не только неудобными, но и неэффективно переносимыми на 32-битное оборудование.

Чтобы решить эту проблему, в язык был добавлен тип long, хотя это требовало C на PDP-11 для генерации нескольких операций для имитации 32-битной арифметики. Даже когда 32-разрядные мини-компьютеры стали доступны наряду с 16-разрядными системами, люди по-прежнему использовали int для повышения эффективности, оставляя long для случаев, когда действительно требовались большие целые числа, поскольку long был заметно менее эффективен в 16-разрядных системах. И short, и long были добавлены в C, что сделало short доступным для 16 бит, long для 32 бит, а int было удобно для производительности. Не было желания запирать числа 16 или 32 в языке, поскольку существовали компиляторы C как минимум для 24- и 36-битных процессоров, а скорее предоставлять имена, которые можно было бы использовать для 32-битных по мере необходимости.

PDP-11 C мог быть повторно реализован с int как 32-битным, что позволило избежать необходимости в long; но это заставило бы людей изменить большинство вариантов использования int на short или столкнуться с серьезным снижением производительности на PDP-11. Помимо потенциального воздействия на исходный код, влияние на существующий объектный код и файлы данных было бы еще хуже даже в 1976 году. влияние изменения размера общего объекта данных в существующей среде настолько велико, что немногие люди будут терпеть это, хотя это может быть приемлемо при создании новой среды. Следовательно, многие поставщики, чтобы избежать конфликтов пространств имен, добавили 64-битное целое число в свои 32-битные среды C, используя новое имя, из которых long long было наиболее широко используемым. [...]

person Christoph    schedule 18.06.2011
comment
Хм, ответ Чарли Мартина получил наибольшее количество голосов, но эта цитата, прямо из первых уст, сильна. Мне особенно нравится, что он описывает это из исторического контекста (это то, что существовало, поэтому мы должны поддерживать это), а не говорить, что в стандарте указано $X. - person davidtbernal; 19.06.2011
comment
Стоит отметить, что на многих старых машинах (и многих небольших встроенных микроконтроллерах даже сегодня) 16-битные числа могут обрабатываться быстрее, чем 32-битные, но на многих новых машинах 32-битные числа могут обрабатываться быстрее, чем 16-битные. битовые числа. Хотя возможность явно запрашивать 16-битные числа в некоторых контекстах полезна, особенно в массивах и структурах, их следует использовать с осторожностью. Если нужна только переменная для обработки чисел +/-32767, полезно иметь возможность запросить, чтобы компилятор использовал любой размер, наиболее удобный для удовлетворения этой потребности. - person supercat; 13.10.2011

Исторически сложилось так, что большинство размеров и типов в C можно проследить до архитектуры PDP-11. Это были байты, слова (16 бит) и двойные слова (32 бита). Когда C и UNIX были перемещены на другую машину (я думаю, Interdata 832), длина слова была 32 бита. Чтобы обеспечить совместимость исходного кода, long и int были определены так, чтобы строго

sizeof(short)sizeof(int)sizeof(long).

Большинство машин теперь заканчиваются sizeof(int) = sizeof(long), потому что 16 бит уже неудобны, но у нас есть long long, чтобы получить 64 бита, если это необходимо.

Обновить строго. Я должен был сказать "компиляторы", потому что разные разработчики компиляторов могут принимать разные решения для одной и той же архитектуры набора инструкций. GCC и Microsoft, например.

person Charlie Martin    schedule 17.06.2011
comment
О вашем обновлении: если вы говорите о long и int с GCC в Windows, MinGW.org (32-разрядная версия) и mingw-w64 (32/64-разрядная версия) придерживаются MS ABI, то есть sizeof(int)==sizeof(long)==4. Я не знаю, поддерживает ли MSVC такие вещи, как long double, но в этом может быть разница. Размер целых чисел часто диктуется на уровне ОС/ABI. - person rubenvb; 17.06.2011
comment
@ Рубен, становится только хуже, когда вы смотрите на некоторые другие компиляторы. Дело в том, что как автор компилятора вы можете довольно свободно выбирать, но это может усложнить написание кода для API ОС и тому подобного. - person Charlie Martin; 17.06.2011

Еще в конце 70-х и начале 80-х многие архитектуры были 16-битными, поэтому обычно char был 8-битным, int — 16-битным, а long — 32-битным. В конце 80-х произошел общий переход на 32-битные архитектуры, поэтому int стал 32-битным, но долгое время оставался 32-битным.

За последние 10 лет произошел переход к 64-битным вычислениям, и теперь у нас есть несколько различных моделей, наиболее распространенной из которых является LP64, где int по-прежнему 32-битные, а long теперь 64-битные.

Итог: не делайте никаких предположений о размерах различных целочисленных типов (кроме того, что определено в стандарте, конечно), и если вам нужны типы фиксированного размера, используйте <stdint.h>.

person Paul R    schedule 17.06.2011

Насколько я понимаю, стандарт C требует, чтобы long имел длину не менее 32 бит и был не меньше длины int. С другой стороны, int всегда (как мне кажется) равно размеру исходного слова архитектуры.

Имейте в виду, что, когда разрабатывались стандарты, 32-битные машины не были распространены; изначально int, вероятно, был бы родным 16-битным, а long был бы вдвое длиннее 32-битного.

person Chowlett    schedule 17.06.2011
comment
С другой стороны, int всегда (я думаю) равен собственному размеру слова архитектуры - это как минимум 16 бит, хотя некоторые 8-битные архитектуры могут даже не иметь размер слова . В стандарте есть довольно расплывчатая формулировка, [int] имеет естественный размер, предложенный архитектурой. Теперь для меня 64-битная архитектура предполагает 64-битный естественный размер, но разработчики C обычно игнорируют это. Итак, я делаю вывод, что расплывчатый язык бессмыслен, int - это тип по определению не менее 16 бит, эмпирически обычно 32, не могу сказать больше. - person Steve Jessop; 17.06.2011
comment
В частности, если кто-то опрометчиво полагает, что естественный размер или размер слова подразумевает, что int имеет тот же размер, что и указатель, то у него появится другое мнение. Я предполагаю, что 64-битные указатели имеют неестественный размер ;-) - person Steve Jessop; 17.06.2011

В 16-разрядных операционных системах int был 16-разрядным, а long — 32-разрядным. После перехода на Win32 обе стали 32-битными. При переходе на 64-битную ОС рекомендуется оставить без изменений длинный размер, это не нарушит существующий код, когда он скомпилирован в 64-битном режиме. Новые типы (например, специфичные для Microsoft __int64, size_t и т. д.) могут использоваться в 64-битных программах.

person Alex F    schedule 17.06.2011