Różnica między size_t i std :: size_t

139

Jakie są różnice między size_ti std::size_tpod względem tego, gdzie są deklarowane, kiedy należy ich używać i jakie są inne cechy wyróżniające?

Mankarse
źródło
Chciałbym wiedzieć, czy specyfikacja C ++ łączy std :: size_t z typem C size_t.
Doug T.
Zobacz podobne pytanie: link
Mankarse

Odpowiedzi:

88

C size_ti C ++ std::size_tsą takie same.

W C jest zdefiniowany w <stddef.h>C ++ iw C ++, jego <cstddef>zawartość jest taka sama jak nagłówek C (zobacz cytat poniżej). Jest określona jako unsigned całkowitą w związku z sizeof operatora.

C Standard mówi w §17.7 / 2,

size_t który jest unsigned całkowitą od wyniku tego sizeof operatora

A C ++ Standard mówi (o cstddefnagłówku) w §18.1 / 3,

Zawartość jest taka sama, jak nagłówek standardowej biblioteki C, z następującymi zmianami .

Więc tak, oba są takie same; Jedyną różnicą jest to, który definiuje c ++ size_tw stdprzestrzeni nazw.

Proszę również zauważyć, że powyższa linia mówi również „z następującymi zmianami”, co nie dotyczy size_t. Odnosi się raczej do nowych dodatków (głównie) wprowadzonych przez C ++ do języka (nieobecnych w C), które również są zdefiniowane w tym samym nagłówku.


Wikipedia ma bardzo dobre informacje na temat zakresu i rozmiaru magazynu size_t:

Zakres i wielkość składowania size_t

Rzeczywisty typ size_t jest zależne od platformy ; wspólny błąd jest założenie size_t jest taka sama jak unsigned int, co może prowadzić do błędów oprogramowania, [3], [4], podczas przemieszczania się z 32 do 64 bitów architektury, na przykład.

Zgodnie z normą ISO C (C99) z 1999 r., Size_t jest liczbą całkowitą bez znaku o długości co najmniej 16 bitów.

A resztę możesz przeczytać na tej stronie w Wikipedii.

Nawaz
źródło
To prowadzi do kolejnego pytania: Jeśli STL już importuje size_t do C (cstddef), dlaczego ma swoją własną inną wersję?
Alok Save
43
@Als: Ściśle mówiąc, błędem jest mówić size_tbez using namespace std;lub using std::size_t;. Jednak większość kompilatorów na to zezwala, a Standard wyraźnie zezwala im na to (§D.5 / 3).
Potatoswatter
9
@Potatoswatter: Z pewnością nie może to być zarówno błąd, jak i wyraźnie dozwolone w standardzie? Jeśli jest w standardzie, nie jest to błąd!
Ben Hymers,
8
@BenHymers Standard określa, co deklarują standardowe nagłówki, i nie mogą one deklarować żadnych innych niezastrzeżonych nazw. Nagłówek <cstddef>może ::size_t, ale nie musi, deklarować , więc nie można polegać na tym, że jest obecny lub nieobecny, chyba że wyraźnie zawiera <stddef.h>lub inny nagłówek z biblioteki C, która gwarantuje, że go zadeklaruje.
Potatoswatter
4
@Potatoswatter: Ach, teraz rozumiem, co masz na myśli! Musiałem być zdezorientowany przez zbyt wiele „przyzwoleń” w jednym zdaniu. Nadal uważam, że twój pierwszy komentarz jest jednak zbyt mocny; jak właśnie powiedziałeś, ::size_tjest obecny np. w <stddef.h>, więc nie zawsze musisz go kwalifikować std::.
Ben Hymers,
16

Z C ++ 03 „17.4.3.1.4 Typy”:

Dla każdego typu T z biblioteki Standard C (przypis 169) typy :: T i std :: T są zarezerwowane dla implementacji, a po zdefiniowaniu :: T powinny być identyczne z std :: T.

I przypis 169:

Te typy to 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 i wint_t.

Michael Burr
źródło
Zatem przenośny kod nie powinien polegać na std::Tdefiniowanych wariantach?
Mankarse
5
@Mankarse: Nie powinieneś polegać na ich zdefiniowaniu, jeśli dołączysz tylko wersję C odpowiedniego nagłówka. Jeśli #include <stddef.h>wtedy możesz std::size_tlub nie być dostępny. Jeśli #include <cstddef>wtedy jesteś std::size_tdostępny, ale size_tmoże nie być.
Dennis Zickefoose
4
@Mankarse: Naprzeciwko. Wersje nagłówków w C ++ muszą je zdefiniować w, std::a akapit mówi, że może również definiować je w przestrzeni nazw najwyższego poziomu, a jeśli tak, musi zdefiniować je identycznie na std::najwyższym poziomie. Większość kompilatorów po prostu dołącza nagłówek C i importuje nazwy do std::, więc symbole są zdefiniowane w obu.
Jan Hudec
4
Osobiście nigdy nie zawracam sobie głowy nagłówkami <cxxxxx> ani std::wariantami identyfikatorów, które pochodzą z brzegu C. Trzymam <xxxxx.h>się standardowych nagłówków C - to nigdy nie był problem. Tak, będę używać <stddef.h>i size_tnigdy nie dać namysłu do std::size_t; w rzeczywistości nigdy nie przychodzi mi do głowy, że istnieje (lub może być) a std::size_t.
Michael Burr
12

std :: size_t jest w rzeczywistości stddef.h „s size_t .

cstddef daje następujące informacje:

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

... skutecznie przenosi poprzednią definicję do przestrzeni nazw standardowej.

hifier
źródło
Jak podkreśla Nawaz, w rzeczywistości jest odwrotnie. Nie możesz uwzględnić <cstddef>i oczekiwać, że otrzymasz ::size_t, ale jeśli to <stddef.h>zrobisz, dostaniesz std::size_t.
MSalters
4
@MSalters, nie śledzę. Włączenie <stddef.h>tylko cię dostanie ::size_t.
hifier
2
To jest więc błąd w twojej implementacji.
MSalters
4
@MSalters, nie całkiem śledzę. Czy nie powinno być odwrotnie? <cstddef> pochodzi z C ++, więc powinien definiować zawartość w std :: *? Z drugiej strony, w nagłówku C, jak stddef.h, spodziewałbym się tylko typu C, czyli :: size_t.
Ela782
11
@MSalters, ponieważ C ++ 11 to nie jest dokładne. Jeśli dołączysz, <cstddef>masz gwarancję otrzymania std::size_ti możesz również otrzymać ::size_t(ale nie jest to gwarantowane). Jeśli dołączysz <stddef.h>, masz gwarancję, że otrzymasz ::size_ti możesz również dostać std::size_t(ale nie jest to gwarantowane). W C ++ 03 było inaczej, ale faktycznie było to niemożliwe do zaimplementowania i naprawione jako usterka.
Jonathan Wakely,