Где мне найти определение 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>

2
Это именно то, что мне нужно, за этот ответ нужно проголосовать.
— neodelphi

27

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

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


Лучший ответ, поскольку он цитирует стандарт.
— Мартин Йорк,

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 {...}если необходимо, чтобы ограничить объем.)


1

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.