Вопрос

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

Это было полезно?

Решение

А size_t тип — это целочисленный тип без знака, который является результатом 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 никогда не бывает отрицательным, и оно максимизирует производительность, поскольку оно определяется как беззнаковый целочисленный тип, достаточно большой (но не слишком большой) для представления размера максимально возможного объекта на целевой платформе.

Размеры никогда не должны быть отрицательными, и действительно 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 это определение типа, которое является псевдонимом для некоторого целочисленного типа без знака, обычно 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) <= sizeof(short) <= sizeof(int) <= sizeof(long), не налагая никаких других ограничений на фактическое представление точности, доступной программисту для каждого из этих примитивных типов.

Примечание:Это НЕ то же самое, что в 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.h', определяют его как знаковый тип.Некоторый код в библиотеке зависит от того, что size_t является беззнаковым типом, и не будет работать правильно, если он подписан.

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

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

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

size_t — размер указателя.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top