Почему size_t лучше?
Название на самом деле немного вводит в заблуждение, но я хотел, чтобы оно было коротким. Я читал о том, почему я должен использовать size_t, и я часто находил такие заявления:
size_t
гарантированно сможет выразить максимальный размер любого объекта, включая любой массив
Я не очень понимаю, что это значит. Есть ли какая-то ограниченность того, сколько памяти вы можете выделить одновременно, и size_t гарантированно будет достаточно большим, чтобы считать каждый байт в этом блоке памяти?
Дополнительный вопрос:
Что определяет, сколько памяти можно выделить?
6 ответов
Допустим, самый большой объект, который может иметь ваш компилятор / платформа, составляет 4 ГБ. size_t
тогда это 32 бит. Теперь предположим, что вы перекомпилируете свою программу на 64-битной платформе, способной поддерживать объекты размером 2^43 - 1. size_t
будет длиной не менее 43 бит (но обычно это будет 64 бит на данный момент). Дело в том, что вам нужно только перекомпилировать программу. Вам не нужно менять все свои int
с long
(если int
32 бит и long
64 бит) или из int32_t
в int64_t
, (если вы спрашиваете себя, почему 43-разрядная версия, допустим, что 64-разрядная версия Windows Server 2008 R2 не поддерживает объекты размером 2^63 и объекты размером 2^62... Она поддерживает 8 ТБ адресуемого пространства... Итак, 43 немного!)
Многие программы, написанные для Windows, считали указатель таким же большим, как DWORD
(32-разрядное целое число без знака). Эти программы не могут быть перекомпилированы на 64 бит без переписывания больших кусков кода. Если бы они использовали DWORD_PTR
(значение без знака гарантированно будет настолько большим, насколько это необходимо, чтобы содержать указатель), у них не было бы этой проблемы.
size_t
"точка" похожа. но разные!
size_t
не может быть в состоянии содержать указатель!!
(DWORD_PTR
Microsoft Windows есть)
Это вообще незаконно
void *p = ...
size_t p2 = (size_t)p;
Например, на старой платформе DOS максимальный размер объекта составлял 64 КБ, поэтому size_t
должно быть 16 бит, НО дальний указатель должен быть не менее 20 бит, потому что 8086 имел пространство памяти 1 МБ (в конце дальний указатель был 16 + 16 бит, потому что память 8086 была сегментирована)
В основном это означает, что size_t
, гарантированно будет достаточно большим, чтобы индексировать любой массив и получить размер любого типа данных.
Это предпочтительнее, чем просто int
, потому что размер int
и другие целочисленные типы могут быть меньше, чем те, которые могут быть проиндексированы. Например int
обычно имеет длину 32 бита, что недостаточно для индексации больших массивов на 64-битных машинах. (Это на самом деле очень распространенная проблема при переносе программ на 64-битную версию.)
Именно в этом причина. Максимальный размер любого объекта в данном языке программирования определяется сочетанием ОС, архитектуры процессора и используемого компилятора / компоновщика.
size_t определяется как достаточно большой, чтобы содержать значение размера максимально возможного объекта.
Обычно это означает, что size_t определен как typedef как самый большой доступный тип int. Таким образом, в 32-битной среде это обычно составляет 4 байта, а в 64-битной системе - 8 байтов.
size_t - это возвращение оператора sizeof (см. 7.17 c99), поэтому он должен описывать максимально возможный объект, который может представлять система.
size_t
определяется для платформы, для которой вы компилируете. Следовательно, он может представлять максимум для этой платформы.