Почему size_t лучше?

Название на самом деле немного вводит в заблуждение, но я хотел, чтобы оно было кратким. Я читал о том, почему я должен использовать size_t, и часто встречал такие утверждения:

size_t гарантированно может выразить максимальный размер любого объекта, включая любой массив

Я не очень понимаю, что это значит. Есть ли какое-то ограничение на объем памяти, который вы можете выделить за один раз, и размер size_t гарантированно будет достаточно большим, чтобы подсчитать каждый байт в этом блоке памяти?

Дополнительный вопрос:
Что определяет, сколько памяти может быть выделено?


person Paul Manta    schedule 21.10.2011    source источник
comment
Также взгляните на этот ответ на этот вопрос для отличного объяснения.   -  person razlebe    schedule 21.10.2011


Ответы (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 была сегментирована)

person xanatos    schedule 21.10.2011
comment
Значит, это максимально возможный целочисленный тип на данной платформе? - person Paul Manta; 21.10.2011
comment
@Paul Нет. У вас все еще может быть 128-битное целое число. Но если size_t 64-битный, а long 128-битный (это допустимо, но я не думаю, что есть компиляторы со 128-битным long), вы все равно не сможете malloc(2^120) - person xanatos; 21.10.2011
comment
Спасибо. Я разместил дополнительный вопрос здесь: stackoverflow.com/questions/7850482/ - person Paul Manta; 21.10.2011
comment
Хорошо, что вы упомянули, что size_t не может содержать указатели: это будет мой следующий вопрос. :П - person Paul Manta; 21.10.2011
comment
@Paul Если ваш следующий вопрос what type is guaranteed to be able to contain any pointer, имейте в виду, что ответ будет void*. ptrdiff_t работает только между элементами одного массива, а не между абсолютными адресами. - person xanatos; 21.10.2011
comment
@Paul, я забыл... В C99 вы можете использовать intptr_t для хранения указателя. - person xanatos; 23.10.2011

В основном это означает, что size_t гарантированно будет достаточно большим, чтобы проиндексировать любой массив и получить размер любого типа данных.

Это предпочтительнее использования только int, потому что размер int и других целочисленных типов может быть меньше, чем то, что может быть проиндексировано. Например, int обычно имеет длину 32 бита, чего недостаточно для индексации больших массивов на 64-битных машинах. (На самом деле это очень распространенная проблема при переносе программ на 64-разрядную версию.)

person Mysticial    schedule 21.10.2011

Именно в этом причина. Максимальный размер любого объекта в данном языке программирования определяется комбинацией ОС, архитектуры ЦП и используемого компилятора/компоновщика.

size_t определяется как достаточно большой, чтобы вместить значение размера максимально возможного объекта.

Обычно это означает, что тип size_t определен как самый большой доступный тип int. Таким образом, в 32-битной среде это обычно будет 4 байта, а в 64-битной системе — 8 байтов.

person Tonny    schedule 21.10.2011

size_t определяется для платформы, для которой вы компилируете. Следовательно, он может представлять максимум для этой платформы.

person Ed Heal    schedule 21.10.2011

size_t является результатом оператора sizeof (см. 7.17 c99), поэтому он должен описывать максимально возможный объект, который может представить система.

person rerun    schedule 21.10.2011

Посмотри на

http://en.wikipedia.org/wiki/Size_t

person cli_hlt    schedule 21.10.2011
comment
Что ж, это прекрасно отвечает на вопрос. Может быть, вопрос, на который легко может ответить Google, также довольно глуп? Но ведь глупых вопросов не бывает? - person cli_hlt; 21.10.2011
comment
@cli_hlt Глупый вопрос кандидата: повредят ли ядерные осадки моей коллекции видеокассет? ;-) - person chux - Reinstate Monica; 31.10.2014