Каковы различия между size_t и std::size_tс точки зрения того, где они объявлены, когда они должны использоваться и каких-либо других отличительных особенностей?
В C он определен в <stddef.h>и в C ++, он определен в том, <cstddef>чье содержимое совпадает с заголовком C (см. Цитату ниже). Это определяется как целое число без знака типа в результате этого SIZEOF оператора.
Стандарт С говорит в §17.7 / 2,
size_t , который является целым числом без знака типа в результате этого SIZEOF оператора
А C ++ Standard говорит (о cstddef заголовке) в §18.1 / 3,
Содержимое совпадает с заголовком библиотеки Standard C со следующими изменениями .
Так что да, оба одинаковы; единственное отличие состоит в том, что C ++ определяет size_tв stdпространстве имен.
Также обратите внимание, что в приведенной выше строке также написано «со следующими изменениями», что не относится к size_t. Это скорее относится к новым дополнениям (в основном), сделанным C ++ в язык (не представлен в C), которые также определены в том же заголовке.
В Википедии есть очень хорошая информация о диапазоне и размере хранилища size_t:
Диапазон и размер хранилища size_t
Фактический тип size_t является
зависит от платформы ; распространенная ошибка
заключается в предположении size_t таким же , как беззнаковый Int, что может привести к ошибкам программирования, [3] [4] при переходе от 32 до 64-битной архитектуры, например.
В соответствии со стандартом ISO C 1999 года (C99) size_t представляет собой целочисленный тип без знака длиной не менее 16 бит.
А остальное вы можете прочитать с этой страницы в википедии.
Это приводит к другому Q. Если STL уже импортирует size_t через C (cstddef), почему он снова имеет свою собственную версию?
Alok Save
43
@ Алс: Строго говоря, ошибочно говорить size_tбез using namespace std;или using std::size_t;. Тем не менее, большинство компиляторов допускают это, и Стандарт специально разрешает им это разрешать (§D.5 / 3).
Potatoswatter
9
@Potatoswatter: Конечно, это не может быть и ошибкой, и конкретно разрешено в стандарте? Если это в стандарте, это не ошибка!
Бен Хаймерс
8
@BenHymers Стандарт определяет, что объявляют стандартные заголовки, и им не разрешается объявлять любые другие незарезервированные имена. Заголовок <cstddef>может или не может объявить ::size_t, так что вы не можете полагаться на то, что он там или отсутствует, если специально не включен <stddef.h>или другой заголовок из библиотеки C, который гарантированно объявит его.
Potatoswatter
4
@Potatoswatter: Ах, теперь я понимаю, что вы имеете в виду! Должно быть, меня смутило слишком много «разрешений» в одном предложении. Я все еще думаю, что ваш первый комментарий слишком силен; как вы только что сказали, ::size_tприсутствует, например, в <stddef.h>, так что вам не всегда нужно его квалифицировать std::.
Бен Хаймерс
16
Из C ++ 03 «17.4.3.1.4 Типы»:
Для каждого типа T из стандартной библиотеки C (сноска 169) типы :: T и std :: T зарезервированы для реализации, и, когда они определены, :: T должен быть идентичен std :: T.
И сноска 169:
К этим типам относятся: clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t и wint_t.
Таким образом, переносимый код не должен полагаться на определяемые std::Tварианты?
Mankarse
5
@Mankarse: Вы не должны полагаться на их определение, если вы включаете только версию C соответствующего заголовка. Если вы #include <stddef.h>тогда std::size_tможете или не можете быть доступны. Если вы #include <cstddef>тогда std::size_tдоступны, но size_tмогут не быть.
Деннис Зикефуз
4
@Mankarse: Опозит. Версии заголовков C ++ должны определять их в, std::а в параграфе говорится, что он может также определять их в пространстве имен верхнего уровня, и если это так, он должен определять их идентично на std::верхнем уровне. Большинство компиляторов просто включают заголовок C и импортируют имена std::, поэтому символы в конечном итоге определяются в обоих.
Ян Худек
4
Лично я никогда не беспокоюсь о заголовках <cxxxxx> или std::вариантах идентификаторов, которые приходят с берега Си. Я придерживаюсь <xxxxx.h>стандартных заголовков C - это никогда не было проблемой. Итак, я бы использовал <stddef.h>и size_tникогда не задумывался std::size_t; на самом деле, мне никогда не приходит в голову, что есть (или может быть) std::size_t.
Как указывает Наваз, на самом деле все наоборот. Вы не можете включить <cstddef>и ожидать получить ::size_t, но если вы включите, <stddef.h>вы получите std::size_t.
MSalters
4
@MSalters, я не подписан. В том числе <stddef.h>достанется только ты ::size_t.
Hifier
2
Это ошибка в вашей реализации.
MSalters
4
@MSalters, я не совсем понимаю. Не должно ли быть наоборот? <cstddef> происходит из C ++, поэтому должен определять материал в std :: *? С другой стороны, в заголовке C, таком как stddef.h, я ожидал бы только тип C, т.е. :: size_t.
Ela782
11
@MSalters, так как C ++ 11 это не точно. Если вы включите, <cstddef>вы гарантированно получите, std::size_tи вы также можете получить ::size_t(но это не гарантировано). Если вы включите, <stddef.h>вы гарантированно получите, ::size_tи вы также можете получить std::size_t(но это не гарантировано). В C ++ 03 все было иначе, но это было практически неосуществимо и исправлено как дефект.
Ответы:
Си
size_t
и Си ++std::size_t
одинаковы.В C он определен в
<stddef.h>
и в C ++, он определен в том,<cstddef>
чье содержимое совпадает с заголовком C (см. Цитату ниже). Это определяется как целое число без знака типа в результате этого SIZEOF оператора.Стандарт С говорит в §17.7 / 2,
А C ++ Standard говорит (о
cstddef
заголовке) в §18.1 / 3,Так что да, оба одинаковы; единственное отличие состоит в том, что C ++ определяет
size_t
вstd
пространстве имен.Также обратите внимание, что в приведенной выше строке также написано «со следующими изменениями», что не относится к
size_t
. Это скорее относится к новым дополнениям (в основном), сделанным C ++ в язык (не представлен в C), которые также определены в том же заголовке.В Википедии есть очень хорошая информация о диапазоне и размере хранилища size_t:
А остальное вы можете прочитать с этой страницы в википедии.
источник
size_t
безusing namespace std;
илиusing std::size_t;
. Тем не менее, большинство компиляторов допускают это, и Стандарт специально разрешает им это разрешать (§D.5 / 3).<cstddef>
может или не может объявить::size_t
, так что вы не можете полагаться на то, что он там или отсутствует, если специально не включен<stddef.h>
или другой заголовок из библиотеки C, который гарантированно объявит его.::size_t
присутствует, например, в<stddef.h>
, так что вам не всегда нужно его квалифицироватьstd::
.Из C ++ 03 «17.4.3.1.4 Типы»:
И сноска 169:
источник
std::T
варианты?#include <stddef.h>
тогдаstd::size_t
можете или не можете быть доступны. Если вы#include <cstddef>
тогдаstd::size_t
доступны, ноsize_t
могут не быть.std::
а в параграфе говорится, что он может также определять их в пространстве имен верхнего уровня, и если это так, он должен определять их идентично наstd::
верхнем уровне. Большинство компиляторов просто включают заголовок C и импортируют именаstd::
, поэтому символы в конечном итоге определяются в обоих.std::
вариантах идентификаторов, которые приходят с берега Си. Я придерживаюсь<xxxxx.h>
стандартных заголовков C - это никогда не было проблемой. Итак, я бы использовал<stddef.h>
иsize_t
никогда не задумывалсяstd::size_t
; на самом деле, мне никогда не приходит в голову, что есть (или может быть)std::size_t
.станд :: size_t фактически stddef.h «s size_t .
cstddef дает следующее:
... эффективно перенести предыдущее определение в пространство имен std.
источник
<cstddef>
и ожидать получить::size_t
, но если вы включите,<stddef.h>
вы получитеstd::size_t
.<stddef.h>
достанется только ты::size_t
.<cstddef>
вы гарантированно получите,std::size_t
и вы также можете получить::size_t
(но это не гарантировано). Если вы включите,<stddef.h>
вы гарантированно получите,::size_t
и вы также можете получитьstd::size_t
(но это не гарантировано). В C ++ 03 все было иначе, но это было практически неосуществимо и исправлено как дефект.