Різниця між size_t та std :: size_t


139

У чому полягають відмінності між ними size_tта std::size_tщодо того, де вони декларуються, коли вони повинні використовуватися та будь-які інші ознаки, що розмежовуються?


Мені буде цікаво дізнатися, чи специфікація C ++ пов'язує std :: size_t з типом C size_t.
Дуг Т.

Дивіться подібне запитання: посилання
Mankarse

Відповіді:


88

C size_tі C ++ std::size_tобоє однакові.

В C він визначений в <stddef.h>і в C ++, його визначено <cstddef>, вміст якого такий же, як і заголовка C (див. Цитата нижче). Її визначають як ціле число без знака типу в результаті цього SIZEOF оператора.

C Стандарт говорить у §17.7 / 2,

size_t , який є цілим числом без знака типу в результаті цього SIZEOF оператора

А C ++ Standard (про cstddefзаголовок) говорить у § 18.1 / 3,

Вміст такий самий, як у заголовку бібліотеки Standard C, із наступними змінами .

Так так, обидва однакові; Єдина відмінність полягає в тому, що C ++ визначає size_tу stdпросторі імен.

Також зверніть увагу, що у наведеному вище рядку також написано "із наступними змінами", на які не йдеться size_t. Її швидше стосуються нових доповнень (здебільшого), внесених C ++ до мови (немає в С), які також визначені в одному заголовку.


У Вікіпедії є дуже хороша інформація про діапазон і розмір пам’яті size_t:

Діапазон і розмір зберігання size_t

Фактичний тип size_t є залежить від платформи ; поширена помилка полягає в припущенні size_t таким же , як беззнаковий Int, що може привести до помилок програмування, [3] [4] при переході від 32 до 64-бітної архітектури, наприклад.

Відповідно до стандарту ISO C 1999 (C99), розмір_t є цілочисловим типом без підпису принаймні 16 біт.

А решту ви можете прочитати з цієї сторінки на wikipedia.


Це приводить до іншого Q, якщо STL вже імпортує size_t через C (cstddef), чому він знову має свою іншу версію?
Алок Зберегти

43
@Als: Строго кажучи, помилка сказати size_tбез using namespace std;або using std::size_t;. Однак більшість компіляторів дозволяє це, а Стандарт спеціально дозволяє їм це дозволити (§D.5 / 3).
Potatoswatter

9
@Potatoswatter: Напевно, це не може бути як помилкою, так і спеціально дозволеною у стандарті? Якщо це в стандарті, це не помилка!
Бен Хімерс

8
@BenHymers Стандарт визначає, що оголошують стандартні заголовки, і їм заборонено оголошувати будь-які інші незарезервовані імена. Заголовок <cstddef>може або не може задекларувати ::size_t, тому ви не можете розраховувати на те, що він там присутній або відсутній, якщо спеціально не включити <stddef.h>або інший заголовок з бібліотеки С, який гарантовано оголошує його.
Potatoswatter

4
@Potatoswatter: Ах, я бачу, що ти маєш на увазі зараз! Мені, мабуть, заплуталося занадто багато "дозволити" в одному реченні. Я все ще думаю, що ваш перший коментар занадто сильний; як ви вже сказали, ::size_tнаприклад, в <stddef.h>, тому вам не завжди потрібно це кваліфікувати std::.
Бен Хімерс

16

Від C ++ 03 "17.4.3.1.4 Види":

Для кожного типу T з бібліотеки Standard 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варіанти?
Манкарсе

5
@Mankarse: Не слід покладатися на їх визначення, якщо ви включаєте лише версію C відповідного заголовка. Якщо ви #include <stddef.h>тоді std::size_tмогли б або не можуть бути недоступні. Якщо ви #include <cstddef>тоді std::size_tє, але size_tможе бути і не.
Dennis Zickefoose

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.


Як зазначає Наваз, це насправді навпаки. Ви не можете включити <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 це було інакше, але це було фактично без змін і було зафіксовано як дефект.
Jonathan Wakely
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.