Где мне найти определение size_t?

123

Я вижу переменные, определенные этим типом, но не знаю, откуда они взялись и каково их назначение. Почему бы не использовать int или unsigned int? (А как насчет других «похожих» типов? Void_t и т. Д.).

Элисео Окампос
источник
Точный вопрос: stackoverflow.com/questions/502856/…
kjfletch
@kjfletch: хххммм, странно, что поиск по запросу 'size_t' (как я делал ранее) не вернул этот вопрос.
Eliseo Ocampos,
1
@Eliseo - функция поиска Stackoverflow ужасна. Вместо этого используйте Google с параметром site: stackoverflow.com.
Michael Burr
8
ОП специально спросил, где мне найти определение size_t? Я приземлился здесь, ища то же самое. В цитируемом дубликате не обсуждается, где найти декларацию.
jww
9
Очевидно, это не тот же вопрос, что и связанный. «Где я что-то найду» - не то же самое, что «В чем разница между» (даже если ответ на один дает ответ на другой). Мой поиск в Google по запросу «c ++, где is size_t definition» привел меня прямо сюда, и я бы пропустил другой вопрос, потому что он другой .
Дэн Ниссенбаум

Ответы:

122

Из Википедии

stdlib.hИ stddef.hзаголовочные файлы определяют тип данных с именем size_t1 , который используется для обозначения размера объекта. Библиотечные функции, которые принимают размеры, ожидают, что они имеют тип size_t, а оператор sizeof оценивает их size_t.

Фактический тип size_tзависит от платформы; распространенной ошибкой является предположение, что size_tэто то же самое, что и unsigned int, что может привести к ошибкам программирования 2, особенно по мере того, как 64-битные архитектуры становятся все более распространенными.

Начиная с C99 7.17.1 / 2

В стандартном заголовке определены следующие типы и макросы stddef.h

<Надрез>

size_t

который является беззнаковым целочисленным типом результата оператора sizeof

Мартин Ливерсаж
источник
2
Например, на Win64, intи unsigned intтипы 32 бита, а size_t составляет 64 бита.
Michael Burr
7
См. Раздел 7.17 и 7.18.3 стандарта ISO C (99) (из которого стандарт C ++)
Мартин Йорк,
3
@LokiAstari, почему бы вам просто не отредактировать ответ, если вы знаете, где он написан в стандарте?
Hi-Angel
Так где же ответ C ++?
Lothar
@Lothar Я думаю, единственная разница в том, что size_t может быть ключевым словом, а в остальном имеет то же значение.
Пол Стелиан
30

Согласно описанию 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>
stefanB
источник
2
Это именно то, что мне нужно, за этот ответ нужно проголосовать.
neodelphi
27

size_t представляет собой целочисленный тип без знака результата оператора sizeof (ISO C99, раздел 7.17.)

sizeofОператор дает размер (в байтах) своего операнда, который может быть выражение в скобках или имя типа. Размер определяется типом операнда. Результат - целое число. Значение результата определяется реализацией, а его тип (беззнаковый целочисленный тип) - size_t(ISO C99, раздел 6.5.3.4.)

fpmurphy
источник
Лучший ответ, поскольку он цитирует стандарт.
Мартин Йорк,
1
@Martin - достаточно верно, но я думаю, что часть вопроса «почему не используется unsigned int» столь же интересна (или даже больше), как часть «что такое size_t», и вы не найдете ее в стандарте ,
Майкл Берр,
Да, вот только там нет «Раздела 17.17 »: п. Редко, никто не сказал ни слова о Void_t
Элисео Окампос
Я принимаю этот ответ, поскольку он отвечает непосредственно на вопрос, но было бы здорово, если бы он дополнялся ответом Майкла.
Элисео Окампос,
58
Жаль, что ваш ответ не говорит мне, какой файл заголовка включить.
Мэтт,
6

Фактически size_tпредставляет собой количество байтов, которые вы можете адресовать. На большинстве современных архитектур за последние 10-15 лет это было 32 бита, что также было размером беззнакового int. Однако мы переходим на 64-битную адресацию, в то время как uint, скорее всего, останется 32-битная (в стандарте C ++ ее размер не гарантируется). Чтобы ваш код, зависящий от размера памяти, переносился между архитектурами, вы должны использовать size_t. Например, такие вещи, как размеры массивов, всегда должны использовать size_t. Если вы посмотрите на стандартные контейнеры, ::size()всегда возвращает size_t.

Также обратите внимание, что в Visual Studio есть опция компиляции, которая может проверять эти типы ошибок под названием «Обнаружение проблем с 64-битной переносимостью».

Мэтт Прайс
источник
2

Таким образом, вы всегда будете знать, какой размер, потому что размер предназначен для определенного типа. Собственный вопрос показывает, что это может быть проблема: это 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к размерам возврата и длины.

Лавинио
источник
2

size_t должен быть определен в заголовках вашей стандартной библиотеки. По моему опыту, обычно это просто typedef для unsigned int. Но дело в том, что это не обязательно. Такие типы, как size_t, позволяют поставщику стандартной библиотеки свободно изменять свои базовые типы данных, если это подходит для платформы. Если вы предполагаете, что size_t всегда является целым без знака (посредством приведения и т. Д.), Вы можете столкнуться с проблемами в будущем, если ваш поставщик изменит size_t, например, на 64-битный тип. По этой причине опасно что-либо предполагать об этом или любом другом типе библиотеки.

Райан
источник
1

Я не знаком с , void_tкроме как в результате поиска Google (он используется в виде vmallocбиблиотеки по Кию-Фонг Vo в AT & T Research - Я уверен , что он используется в других библиотеках, а).

Различные определения типов xxx_t используются для абстрагирования типа от конкретной конкретной реализации, поскольку конкретные типы, используемые для определенных вещей, могут отличаться от одной платформы к другой. Например:

  • size_t абстрагирует тип, используемый для хранения размера объектов, потому что в некоторых системах это будет 32-битное значение, в других - 16-битное или 64-битное.
  • Void_tабстрагирует тип указателя, возвращаемого vmallocбиблиотечными подпрограммами, потому что он был написан для работы в системах, предшествующих ANSI / ISO C, где voidключевое слово могло не существовать. По крайней мере, я так думаю.
  • wchar_t абстрагирует тип, используемый для широких символов, поскольку в некоторых системах это будет 16-битный тип, в других - 32-битный тип.

Поэтому, если вы напишете свой код обработки широких символов, чтобы использовать wchar_tтип вместо, скажем unsigned short, этого кода, вероятно, будет более переносимым на различные платформы.

Майкл Берр
источник
Отчасти это то, что я искал. Как я сказал в комментарии к ответу fpmurphy, было бы здорово, если бы его можно было дополнить этим ответом (если вы не возражаете, возможно, вы можете его отредактировать) :)
Элисео Окампос
1

В минималистичных программах, где size_tопределение не было загружено «случайно» в некоторые включения, но оно мне все еще нужно в каком-то контексте (например, для доступа std::vector<double>), я использую этот контекст для извлечения правильного типа. Например typedef std::vector<double>::size_type size_t.

(Обведите, namespace {...}если необходимо, чтобы ограничить объем.)

alfC
источник
1

Что касается «Почему бы не использовать int или unsigned int?», Просто потому, что это семантически более значимо не использовать. Есть практическая причина, по которой его можно, скажем, использовать typedefкак d, а intзатем обновить его до более longпоздней версии, конечно, без изменения кода, но более фундаментально, чем то, что тип должен быть значимым. Чтобы значительно упростить, переменная типа size_tподходит и используется для хранения размеров вещей, точно так же, как time_tи для значений времени. То, как они на самом деле реализованы, должно быть задачей самой реализации. По сравнению с простым вызовом всего int, использование таких значимых имен типов помогает прояснить смысл и цель вашей программы, как это делает любой богатый набор типов.

Crowman
источник