unsigned int против размера t

Я замечаю, что современный код C и c++, похоже, использует size_t вместо int/unsigned int практически везде - от параметров для строковых функций C до STL. Мне любопытно, почему это происходит и какие выгоды это приносит.

8 ответов


на size_t type-это целочисленный тип без знака, который является результатом sizeof оператор (и offsetof оператор), поэтому он гарантированно будет достаточно большим, чтобы содержать размер самого большого объекта, который может обрабатывать ваша система (например, статический массив 8 ГБ).

на size_t тип может быть больше, равна или меньше unsigned int и ваш компилятор может делать предположения о его оптимизации.

вы можете найти более точную информацию в C99 стандарт, раздел 7.17, проект которого доступен в Интернете по адресу pdf формат, или в стандарте C11, раздел 7.19, также доступный как PDF файл проекта.


классический C (ранний диалект C, описанный Брайаном Керниганом и Деннисом Ричи на языке программирования C, 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 требует, чтобы a long занимать не менее 32 бит. Платформа IP16L32 реализует каждый 32-разрядный длиной в пару 16-разрядных слов. Почти все 32-битные операторы на этих платформах требуют двух инструкций, если не больше, потому что они работают с 32 битами в двух 16-битных кусках. Например, для перемещения 32-битной длины обычно требуется две машинные инструкции - одна для перемещения каждого 16-битного фрагмента.

используя size_t предотвращает потери производительности. Согласно эта фантастическая статья "тип size_t - Это typedef, который является псевдонимом для некоторого целочисленного типа без знака, обычно unsigned int или unsigned long, но и, возможно, даже unsigned long long. Каждая стандартная реализация C должна выбрать целое число без знака, которое достаточно велико-но не больше, чем необходимо-для представления размера максимально возможного объекта на целевой платформе."


тип 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)

Примечание: это не то же самое, что в Java (который фактически определяет битовую точность для каждого из типов "char", "byte", "short", " int " и "long").


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

например, в 64-битных системах int и unsigned int могут быть 32-битными, но size_t должен быть достаточно большим, чтобы хранить номера больше, чем 4G


эта выдержка из руководства glibc 0.02 также может быть актуальна при исследовании темы:

существует потенциальная проблема с типом size_t и версиями GCC до выпуска 2.4. ANSI C требует, чтобы size_t всегда был типом без знака. Для совместимости с файлами заголовков существующих систем GCC определяет size_t в stddef.h' to be whatever type the system'ssys / types.h ' определяет это как быть. Большинство систем Unix, которые определяют size_t в ' sys / types.сек, определить его тип. Некоторый код в библиотеке зависит на size_t является беззнаковым типом и не будет работать правильно, если он подписан.

код библиотеки GNU C, который ожидает, что size_t будет без знака, является правильным. Определение size_t как подписанного типа неверно. Мы планируем, что в версии 2.4 GCC всегда будет определять size_t как тип без знака, а fixincludes' script will massage the system'ssys / types.ч' чтобы не конфликтовать с этим.

тем временем мы обходим эту проблему, явно говоря GCC использовать неподписанный тип для size_t, когда компиляция библиотеки GNU C. 'configure' автоматически определит, какой тип GCC использует для size_t, чтобы переопределить его при необходимости.


если мой компилятор установлен в 32 бит,size_t - Это не что иное, как typedef для unsigned int. Если мой компилятор установлен в 64 бит,size_t - Это не что иное, как typedef для unsigned long long.


size_t-это размер указателя.

таким образом, в 32 битах или общей модели ILP32 (integer, long, pointer) size_t составляет 32 бита. и в 64 битах или общей модели LP64 (long, pointer) size_t составляет 64 бита (целые числа по-прежнему 32 бита).

есть и другие модели, но это те, что G++ использовать (по крайней мере по умолчанию)