Почему size_t, когда int будет достаточным для размера массива?
Стандарт C гарантирует, что int
может хранить все возможные размеры массива. По крайней мере, это то, что я понимаю из чтения §6.5.2.1, подраздел 1 (Ограничения подписи):
Одно из выражений должно иметь тип '' указатель на тип объекта, другое выражение должно имеют целочисленный тип, а результат имеет тип type.
Поскольку мы будем использовать int
как индексы массива, почему мы должны использовать size_t
для определения размера массива?
Почему strlen()
возвращает size_t
, когда int
будет достаточно?
Ответы
Ответ 1
Термин "целочисленный тип" не означает int
- например, char
, а short
- целые типы.
Просто потому, что вы можете использовать int
для подстроки массива, не обязательно означает, что он может достигать всех возможных элементов массива.
Более конкретно, size_t
vs. int
, одним из примеров может быть платформа, где int
может быть 16-разрядным типом, а size_t
может быть 32-разрядным (или более обычным 32-разрядным int
против 64-разрядной разницы size_t
на сегодняшних 64-разрядных платформах).
Ответ 2
целочисленный тип не обязательно является "int". "long long" также является целым типом, как и "size_t".
Массивы могут быть больше 2 ГБ. Это свойство весьма удобно для тех, кто пишет голодные программы для хранения данных, например СУБД с большими пулами буферов, серверы приложений с большими кэшами памяти и т.д. Массивы размером более 2 ГБ /4 ГБ - это всего лишь 64-разрядные вычисления:)
size_t для strlen(), по крайней мере, звучит совместимо с тем, как C-стандартный обрабатывает массивы, имеет ли он практический смысл или нет, или кто-то видел большие строки, это другой вопрос.
Ответ 3
Во-первых, то, что вы указали из стандарта, не содержит ссылок на тип int
. И нет, int
не может быть достаточным для хранения размера любого объекта (включая массивы) в C.
Во-вторых, язык C на самом деле не имеет "подписки на массивы". Подписка на массивы реализована с помощью арифметики указателя. И интегральный операнд в арифметике указателя имеет тип ptrdiff_t
. Не size_t
, а не int
, но ptrdiff_t
. Это подписанный тип, BTW, что означает, что значение может быть отрицательным.
В-третьих, целью size_t
является сохранение размера любого объекта в программе (т.е. сохранение результата sizeof
). Он не предназначен для использования в качестве индекса массива. Это просто работает как индекс массива, поскольку гарантируется, что он всегда достаточно велик, чтобы индексировать любой массив. Однако с абстрактной точки зрения "массив" представляет собой определенный тип "контейнера", и есть другие типы контейнеров (списки на основе, древовидные и т.д.). В общем случае size_t
недостаточно для хранения размера любого контейнера, что в общем случае делает его сомнительным выбором для индексации массива. (strlen
, с другой стороны, это функция, которая работает с массивами специально, что делает там size_t
.)
Ответ 4
Когда был написан стандарт C, для машин было типично 16-битный тип "int", и он не мог обрабатывать ни один объект размером больше 65535
байтов, но тем не менее он способен обрабатывать объекты размером более 32767 байт.
Так как арифметика на unsigned int будет достаточно большой, чтобы обрабатывать наибольшие
размер таких объектов, но арифметика на подписанном int не была бы определена, size_t
быть неподписанным, чтобы разместить такие объекты без необходимости использовать "длинные",
вычисления.
На машинах, где максимально допустимый размер объекта находится между INT_MAX и
UINT_MAX, разница между указателями на начало и конец таких
объект может быть слишком большим, чтобы соответствовать "int". Хотя Стандарт не налагает
любые требования к тому, как реализация должна справиться с этим, общий подход
состоит в том, чтобы определить поведение целочисленного и указательного обертывания таким образом, что если S и E
являются указателями на начало и конец char [49152], тогда даже если E-S
превысит INT_MAX, он даст значение, которое при добавлении к S будет
выход E.
В настоящее время редко существует реальное преимущество в том, что size_t является
unsigned type (поскольку код, который требует объектов размером более 2 ГБ, часто
необходимо использовать 64-битные указатели по другим причинам), и это вызывает много видов
сравнения с размерами объектов, которые ведут себя контр-интуитивно, но
факт, что выражения sizeof дают неподписанный тип достаточно хорошо
что он вряд ли когда-либо изменится.
Ответ 5
size_t - это typedef целого числа без знака (например, int или long).
В некоторых 64-битных платформах int может быть 32 бит, а size_t может быть 64 бит.
Используется как более стандартный способ для размера.