Почему числовые типы данных в C имеют такой размер?

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

Ответ дает книга «Computer Science: A Programmer’s Perspective» за авторством Рендела Брайанта и Девида О’Халарона.

Компьютеры и компиляторы поддерживают различные типы для хранения данных — в частности, целых чисел и чисел с плавающей запятой. Каждый отдельный тип может отличаться от других, например, способом представления хранимой информации и объемом занимаемой памяти.

Язык программирования C поддерживает различные типы для хранения как целых чисел, так и чисел с плавающей запятой. Символьный тип char, обычно используемый для представления отдельного символа, может также хранить беззнаковые числа. Более распространенный для этих целей int образует целое семейство типов за счет возможных префиксов: short, long и long long — и все различных размеров. В таблице ниже указано, сколько байт занимает в памяти каждый тип в зависимости от разрядности системы.

pic0
Можно заметить, что размер зависит от разрядности машины (строго говоря, еще и от реализации компилятора). Но почему размеры именно такие? Обратите внимание: short, «обычный» int и long long всегда имеют постоянные размеры в 2, 4 и 8 байт соответственно. Префикс long же означает, что для хранения данной переменной нужно использовать одно машинное слово — 4 байта на 32-битной машине и 8 байт на 64-битной соответственно.

Та же ситуация и с указателями (char*): в системе для хранения адресов используется все то же одно машинное слово, размер которого зависит от разрядности.

Перевод  пункта 2.1.3 «Data sizes» из книги «Computer Science: A Programmer’s Perspective»