size_t
Тип является целым числом без знака тип , который является результатом sizeof
оператора (и offsetof
оператора), поэтому он гарантированно будет достаточно большим , чтобы содержать размер самого большого объекта система может обрабатывать (например, статический массив 8Gb).
size_t
Типа может быть больше, равно или меньше , чем unsigned int
, и компилятор может делать предположения об этом для оптимизации.
Вы можете найти более точную информацию в стандарте C99, раздел 7.17, черновик которого доступен в Интернете в формате pdf , или в стандарте C11, раздел 7.19, который также доступен в виде PDF-документа .
size_t
могут представлять! Если нет, то кто?Классический C (ранний диалект C, описанный Брайаном Керниганом и Деннисом Ритчи в The C Programming Language, Prentice-Hall, 1978) не предоставил
size_t
. Комитет по стандартам C введенsize_t
для устранения проблемы переносимостиПодробно объяснено на Embedded.com (с очень хорошим примером)
источник
Короче говоря,
size_t
никогда не бывает отрицательным, и это максимизирует производительность, потому что это typedef'd, чтобы быть целым типом без знака, который достаточно большой - но не слишком большой - чтобы представить размер максимально возможного объекта на целевой платформе.Размеры никогда не должны быть отрицательными, и это действительно
size_t
тип без знака. Кроме того, посколькуsize_t
без знака, вы можете хранить числа, которые примерно в два раза больше, чем у соответствующего типа со знаком, потому что мы можем использовать бит знака для представления величины, как и все другие биты в целом числе без знака. Когда мы получаем еще один бит, мы умножаем диапазон чисел, которые мы можем представить, примерно в два раза.Итак, вы спросите, почему бы просто не использовать
unsigned int
? Возможно, он не сможет вместить достаточно большие числа. В реализации, гдеunsigned int
32 бита, наибольшее число, которое он может представлять, -4294967295
. Некоторые процессоры, такие как IP16L32, могут копировать объекты размером более4294967295
байтов.Итак, вы спросите, почему бы не использовать
unsigned long int
? Это требует снижения производительности на некоторых платформах. Стандарт C требует, чтобы онlong
занимал не менее 32 бит. Платформа IP16L32 реализует каждый 32-разрядный код в виде пары 16-разрядных слов. Почти всем 32-битным операторам на этих платформах требуются две инструкции, если не больше, потому что они работают с 32-битными в двух 16-битных блоках. Например, для перемещения 32-битной длины обычно требуются две машинные инструкции - по одной для перемещения каждой 16-битной порции.Использование
size_t
позволяет избежать потери производительности. Согласно этой фантастической статье , «Типsize_t
- это typedef, который является псевдонимом для некоторого целого типа без знака, как правило,unsigned int
илиunsigned long
, возможно, дажеunsigned long long
. Предполагается, что каждая реализация Standard C выбирает целое число без знака, которое достаточно велико - но не больше, чем нужно - представлять размер максимально возможного объекта на целевой платформе. "источник
unsigned int
и оно варьируется от одной системы к другой. Это должно быть как минимум65536
, но обычно4294967295
и может быть18446744073709551615
(2 ** 64-1) в некоторых системах.unsigned char
). Стандарт, кажется, нигде не содержит строку «65535» или «65536», а «+32767» встречается только (1.9: 9) в примечании как возможное наибольшее целое число, представимое вint
; гарантия не дается даже, чтоINT_MAX
не может быть меньше, чем это!Тип size_t - это тип, возвращаемый оператором sizeof. Это целое число без знака, способное выражать размер в байтах любого диапазона памяти, поддерживаемого на хост-машине. Он (как правило) связан с ptrdiff_t тем, что ptrdiff_t является целочисленным значением со знаком, так что sizeof (ptrdiff_t) и sizeof (size_t) равны.
При написании кода на C вы всегда должны использовать size_t при работе с диапазонами памяти.
Тип int, с другой стороны, в основном определяется как размер целого значения (со знаком), которое хост-машина может использовать для наиболее эффективного выполнения целочисленной арифметики. Например, на многих старых компьютерах типа ПК значение sizeof (size_t) будет равно 4 (байты), а sizeof (int) будет равно 2 (байт). 16-битная арифметика была быстрее, чем 32-битная арифметика, хотя процессор мог обрабатывать (логическое) пространство памяти до 4 ГиБ.
Используйте тип int только тогда, когда вы заботитесь об эффективности, поскольку его фактическая точность сильно зависит как от параметров компилятора, так и от архитектуры машины. В частности, стандарт C определяет следующие инварианты: sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) и не устанавливает других ограничений на фактическое представление точности, доступной программисту для каждого из эти примитивные типы.
Примечание: это НЕ то же самое, что в Java (которая фактически определяет битовую точность для каждого из типов 'char', 'byte', 'short', 'int' и 'long').
источник
size_t
Способен отображать размер любого отдельного объекта (например: число, массив, структура). Весь диапазон памяти может превышатьsize_t
size_t
- я надеюсь, вы не имеете в виду это. Большую часть времени мы не имеем дело с массивами, где кардинальность адресного пространства + переносимость имеют значение. В этих случаях вы бы взялиsize_t
. В любом другом случае вы берете индексы из (подписанных) целых чисел. Потому что путаница (которая приходит без предупреждения), возникающая из-за непредвиденного недопустимого поведения неподписанных, встречается чаще и хуже проблем переносимости, которые могут возникнуть в других случаях.Тип size_t должен быть достаточно большим, чтобы хранить размер любого возможного объекта. Целое число без знака не должно удовлетворять этому условию.
Например, в 64-битных системах int и unsigned int могут иметь ширину 32 бита, но size_t должен быть достаточно большим, чтобы хранить числа больше 4G.
источник
size_t
что он должен был бы быть настолько большим, если бы компилятор мог принять тип X такой, чтобы sizeof (X) давал значение больше 4G. Напримерtypedef unsigned char foo[1000000000000LL][1000000000000LL]
, большинство компиляторов будут отклонены , и дажеfoo[65536][65536];
могут быть законно отклонены, если он превысит задокументированный предел реализации.Этот отрывок из руководства glibc 0.02 также может быть актуален при исследовании темы:
Существует потенциальная проблема с типом size_t и версиями GCC до выпуска 2.4. ANSI C требует, чтобы size_t всегда был беззнаковым типом. Для совместимости с заголовочными файлами существующих систем, GCC определяет size_t в
stddef.h' to be whatever type the system's
sys / types.h и определяет его как. Большинство систем Unix, которые определяют size_t в `sys / types.h ', определяют его как тип со знаком. Некоторый код в библиотеке зависит от size_t, являющегося типом без знака, и не будет работать правильно, если он подписан.Код библиотеки GNU C, который ожидает, что size_t будет без знака, является правильным. Определение size_t как подписанного типа неверно. Мы планируем, что в версии 2.4 GCC всегда будет определять size_t как тип без знака и
fixincludes' script will massage the system's
sys / types.h ', чтобы не конфликтовать с этим.Тем временем, мы обходим эту проблему, явно говоря GCC, чтобы при компиляции библиотеки GNU C использовался тип unsigned для size_t. `configure 'автоматически определит, какой тип GCC использует для size_t, чтобы переопределить его при необходимости.
источник
Если мой компилятор установлен на 32 бит,
size_t
это не что иное, как typedef дляunsigned int
. Если мой компилятор установлен на 64 бит,size_t
это не что иное, как typedef дляunsigned long long
.источник
unsigned long
для обоих случаев на некоторых ОС.size_t - размер указателя.
Таким образом, в 32-битной или общей ILP32 (целое, длинное, указатель) модель size_t составляет 32 бита. и в 64-битной или обычной модели LP64 (long, pointer) size_t равен 64 битам (целые числа по-прежнему 32 бит).
Существуют и другие модели, но именно они используют g ++ (по крайней мере, по умолчанию).
источник
size_t
не обязательно такой же размер, как указатель, хотя обычно это так. Указатель должен указывать на любое место в памяти;size_t
должен быть достаточно большим, чтобы представлять размер самого большого отдельного объекта.