Я вижу переменные, определенные этим типом, но не знаю, откуда они взялись и каково их назначение. Почему бы не использовать int или unsigned int? (А как насчет других «похожих» типов? Void_t и т. Д.).
Я вижу переменные, определенные этим типом, но не знаю, откуда они взялись и каково их назначение. Почему бы не использовать int или unsigned int? (А как насчет других «похожих» типов? Void_t и т. Д.).
Ответы:
Из Википедии
stdlib.h
Иstddef.h
заголовочные файлы определяют тип данных с именемsize_t
1 , который используется для обозначения размера объекта. Библиотечные функции, которые принимают размеры, ожидают, что они имеют типsize_t
, а оператор sizeof оценивает ихsize_t
.Фактический тип
size_t
зависит от платформы; распространенной ошибкой является предположение, чтоsize_t
это то же самое, что и unsigned int, что может привести к ошибкам программирования 2, особенно по мере того, как 64-битные архитектуры становятся все более распространенными.
Начиная с C99 7.17.1 / 2
В стандартном заголовке определены следующие типы и макросы
stddef.h
<Надрез>
size_t
который является беззнаковым целочисленным типом результата оператора sizeof
int
и unsigned int
типы 32 бита, а size_t составляет 64 бита.
Согласно описанию size_t на en.cppreference.com size_t
определены следующие заголовки:
std::size_t
...
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
size_t
представляет собой целочисленный тип без знака результата оператора sizeof (ISO C99, раздел 7.17.)
sizeof
Оператор дает размер (в байтах) своего операнда, который может быть выражение в скобках или имя типа. Размер определяется типом операнда. Результат - целое число. Значение результата определяется реализацией, а его тип (беззнаковый целочисленный тип) - size_t
(ISO C99, раздел 6.5.3.4.)
Фактически size_t
представляет собой количество байтов, которые вы можете адресовать. На большинстве современных архитектур за последние 10-15 лет это было 32 бита, что также было размером беззнакового int. Однако мы переходим на 64-битную адресацию, в то время как uint
, скорее всего, останется 32-битная (в стандарте C ++ ее размер не гарантируется). Чтобы ваш код, зависящий от размера памяти, переносился между архитектурами, вы должны использовать size_t
. Например, такие вещи, как размеры массивов, всегда должны использовать size_t
. Если вы посмотрите на стандартные контейнеры, ::size()
всегда возвращает size_t
.
Также обратите внимание, что в Visual Studio есть опция компиляции, которая может проверять эти типы ошибок под названием «Обнаружение проблем с 64-битной переносимостью».
Таким образом, вы всегда будете знать, какой размер, потому что размер предназначен для определенного типа. Собственный вопрос показывает, что это может быть проблема: это int
или нет unsigned int
? Кроме того , что величина ( short
, int
, long
и т.д.)?
Поскольку назначен определенный тип, вам не нужно беспокоиться о длине или подписи.
Фактическое определение можно найти в Справочной библиотеке C ++ , в которой говорится:
Тип:
size_t
(Целочисленный тип без знака)Заголовок:
<cstring>
size_t
соответствует интегральному типу данных, возвращаемому оператором языка,sizeof
и определяется в<cstring>
заголовочном файле (среди прочего) как беззнаковый интегральный тип.В
<cstring>
, он используется как тип параметраnum
в функцииmemchr
,memcmp
,memcpy
,memmove
,memset
,strncat
,strncmp
,strncpy
иstrxfrm
, что во всех случаях используется , чтобы указать максимальное количество байтов или символов , функция должна влиять.Он также используется в качестве возвращаемого типа для
strcspn
,strlen
,strspn
иstrxfrm
к размерам возврата и длины.
size_t должен быть определен в заголовках вашей стандартной библиотеки. По моему опыту, обычно это просто typedef для unsigned int. Но дело в том, что это не обязательно. Такие типы, как size_t, позволяют поставщику стандартной библиотеки свободно изменять свои базовые типы данных, если это подходит для платформы. Если вы предполагаете, что size_t всегда является целым без знака (посредством приведения и т. Д.), Вы можете столкнуться с проблемами в будущем, если ваш поставщик изменит size_t, например, на 64-битный тип. По этой причине опасно что-либо предполагать об этом или любом другом типе библиотеки.
Я не знаком с , void_t
кроме как в результате поиска Google (он используется в виде vmalloc
библиотеки по Кию-Фонг Vo в AT & T Research - Я уверен , что он используется в других библиотеках, а).
Различные определения типов xxx_t используются для абстрагирования типа от конкретной конкретной реализации, поскольку конкретные типы, используемые для определенных вещей, могут отличаться от одной платформы к другой. Например:
Void_t
абстрагирует тип указателя, возвращаемого vmalloc
библиотечными подпрограммами, потому что он был написан для работы в системах, предшествующих ANSI / ISO C, где void
ключевое слово могло не существовать. По крайней мере, я так думаю.wchar_t
абстрагирует тип, используемый для широких символов, поскольку в некоторых системах это будет 16-битный тип, в других - 32-битный тип.Поэтому, если вы напишете свой код обработки широких символов, чтобы использовать wchar_t
тип вместо, скажем unsigned short
, этого кода, вероятно, будет более переносимым на различные платформы.
В минималистичных программах, где size_t
определение не было загружено «случайно» в некоторые включения, но оно мне все еще нужно в каком-то контексте (например, для доступа std::vector<double>
), я использую этот контекст для извлечения правильного типа. Например typedef std::vector<double>::size_type size_t
.
(Обведите, namespace {...}
если необходимо, чтобы ограничить объем.)
Что касается «Почему бы не использовать int или unsigned int?», Просто потому, что это семантически более значимо не использовать. Есть практическая причина, по которой его можно, скажем, использовать typedef
как d, а int
затем обновить его до более long
поздней версии, конечно, без изменения кода, но более фундаментально, чем то, что тип должен быть значимым. Чтобы значительно упростить, переменная типа size_t
подходит и используется для хранения размеров вещей, точно так же, как time_t
и для значений времени. То, как они на самом деле реализованы, должно быть задачей самой реализации. По сравнению с простым вызовом всего int
, использование таких значимых имен типов помогает прояснить смысл и цель вашей программы, как это делает любой богатый набор типов.