Разница между size_t и std :: size_t

139

Каковы различия между size_t и std::size_tс точки зрения того, где они объявлены, когда они должны использоваться и каких-либо других отличительных особенностей?

Mankarse
источник
Мне было бы интересно узнать, связывает ли спецификация C ++ std :: size_t с типом C size_t.
Даг Т.
Смотрите похожие вопросы: ссылка
Mankarse

Ответы:

88

Си 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.
Майкл Берр
12

станд :: size_t фактически stddef.h «s size_t .

cstddef дает следующее:

#include <stddef.h>
namespace std 
{
  using ::ptrdiff_t;
  using ::size_t;
}

... эффективно перенести предыдущее определение в пространство имен std.

hifier
источник
Как указывает Наваз, на самом деле все наоборот. Вы не можете включить <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 все было иначе, но это было практически неосуществимо и исправлено как дефект.
Джонатан Уэйкли