Was sind die Unterschiede zwischen size_tund std::size_tin Bezug darauf, wo sie deklariert werden, wann sie verwendet werden sollten und welche anderen Unterscheidungsmerkmale?
In C ist es in <stddef.h>und in C ++ definiert, in <cstddef>dessen Inhalt der C-Header identisch ist (siehe das folgende Zitat). Es ist als vorzeichenloser Integer-Typ des Ergebnisses des Operators sizeof definiert .
C Standard sagt in §17.7 / 2,
size_t ist der vorzeichenlose Integer-Typ des Ergebnisses des Operators sizeof
Und C ++ Standard sagt (über cstddefHeader) in §18.1 / 3,
Der Inhalt entspricht dem Standard-C-Bibliotheksheader mit den folgenden Änderungen .
Also ja, beide sind gleich; Der einzige Unterschied besteht darin, dass C ++ size_tim stdNamespace definiert .
Bitte beachten Sie auch, dass in der obigen Zeile auch "mit den folgenden Änderungen" steht, auf die nicht Bezug genommen wird size_t. Es bezieht sich eher auf die neuen Ergänzungen (meistens), die C ++ in der Sprache (nicht in C vorhanden) vorgenommen hat und die ebenfalls im selben Header definiert sind.
Wikipedia hat sehr gute Informationen über Reichweite und Speichergröße von size_t:
Bereich und Speichergröße von size_t
Der tatsächliche Typ von size_t ist
plattformabhängig . Ein häufiger Fehler
besteht darin, anzunehmen, dass size_t mit int ohne Vorzeichen identisch ist, was zu Programmierfehlern führen kann, [3] [4] beispielsweise beim Übergang von einer 32- zu einer 64-Bit-Architektur.
Gemäß dem ISO C-Standard von 1999 (C99) ist size_t ein vorzeichenloser Integer-Typ mit mindestens 16 Bit.
Und den Rest können Sie von dieser Seite auf Wikipedia lesen .
Das bringt zu einem anderen Q: Wenn STL bereits size_t über C (cstddef) importiert, warum hat es dann wieder eine eigene Version?
Alok Save
43
@Als: Genau genommen ist es ein Fehler, size_tohne using namespace std;oder zu sagen using std::size_t;. Die meisten Compiler erlauben dies jedoch, und der Standard erlaubt es ihnen ausdrücklich, dies zuzulassen (§D.5 / 3).
Potatoswatter
9
@ Potatoswatter: Sicherlich kann es nicht sowohl ein Fehler sein als auch im Standard ausdrücklich erlaubt sein? Wenn es im Standard ist, ist es kein Fehler!
Ben Hymers
8
@BenHymers Der Standard gibt an, was die Standardheader deklarieren, und sie dürfen keine anderen nicht reservierten Namen deklarieren. Der Header <cstddef>kann deklariert werden oder nicht ::size_t, sodass Sie sich nicht darauf verlassen können, dass er vorhanden ist oder fehlt, es sei denn, Sie enthalten ausdrücklich einen <stddef.h>anderen Header aus der C-Bibliothek, der ihn garantiert deklariert.
Potatoswatter
4
@ Potatoswatter: Ah, ich verstehe was du jetzt meinst! Ich muss durch zu viele "Erlaubnisse" in einem Satz verwirrt worden sein. Ich denke immer noch, dass Ihr erster Kommentar zu stark ist; Wie Sie gerade gesagt haben, ::size_tist zB in vorhanden <stddef.h>, so dass Sie es nicht immer mit qualifizieren müssen std::.
Ben Hymers
16
Ab C ++ 03 "17.4.3.1.4 Typen":
Für jeden Typ T aus der Standard C-Bibliothek (Fußnote 169) sind die Typen :: T und std :: T der Implementierung vorbehalten, und wenn definiert, muss :: T mit std :: T identisch sein.
Und Fußnote 169:
Diese Typen sind 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 und wint_t.
Portabler Code sollte sich also nicht auf die std::Tdefinierten Varianten verlassen ?
Mankarse
5
@Mankarse: Sie sollten sich nicht darauf verlassen, dass sie definiert werden, wenn Sie nur die C-Version des entsprechenden Headers einschließen. Wenn Sie #include <stddef.h>dann std::size_tmöglicherweise verfügbar sind oder nicht. Wenn Sie #include <cstddef>dann std::size_tverfügbar sind, aber size_tmöglicherweise nicht.
Dennis Zickefoose
4
@Mankarse: Das Gegenteil. Die C ++ - Versionen der Header müssen sie in definieren, std::und der Absatz besagt, dass sie möglicherweise auch im Namespace der obersten Ebene definiert werden. Wenn dies der Fall ist, müssen sie in std::und auf oberster Ebene identisch definiert werden. Die meisten Compiler enthalten nur den C-Header und importieren die Namen in std::, sodass die Symbole in beiden definiert werden.
Jan Hudec
4
Persönlich beschäftige ich mich nie mit den <cxxxxx> -Headern oder den std::Varianten von Bezeichnern, die vom C-Ufer kommen. Ich bleibe bei <xxxxx.h>den Standard-C-Headern - es war nie ein Problem. Also würde ich verwenden <stddef.h>und size_tniemals darüber nachdenken std::size_t; Tatsächlich fällt mir nie ein, dass es eine gibt (oder geben könnte) std::size_t.
Wie Nawaz betont, ist es tatsächlich umgekehrt. Sie können nicht einschließen <cstddef>und erwarten zu bekommen ::size_t, aber wenn Sie einschließen, werden <stddef.h>Sie bekommen std::size_t.
MSalters
4
@ MSalters, ich folge nicht. Einschließlich <stddef.h>wird nur Sie bekommen ::size_t.
Hifier
2
Das ist also ein Fehler in Ihrer Implementierung.
MSalters
4
@ MSalters, ich folge nicht ganz. Sollte es nicht umgekehrt sein? <cstddef> kommt aus C ++, sollte also das Zeug in std :: * definieren? Andererseits würde ich in einem C-Header wie stddef.h nur den C-Typ erwarten, dh :: size_t.
Ela782
11
@ MSalters, da C ++ 11 nicht korrekt ist. Wenn Sie einschließen, werden <cstddef>Sie garantiert bekommen std::size_tund Sie könnten auch bekommen ::size_t(aber es ist nicht garantiert). Wenn Sie einschließen, werden <stddef.h>Sie garantiert bekommen ::size_tund Sie könnten auch bekommen std::size_t(aber es ist nicht garantiert). In C ++ 03 war das anders, aber das war praktisch nicht umsetzbar und wurde als Fehler behoben.
Antworten:
C
size_t
und C ++std::size_t
sind beide gleich.In C ist es in
<stddef.h>
und in C ++ definiert, in<cstddef>
dessen Inhalt der C-Header identisch ist (siehe das folgende Zitat). Es ist als vorzeichenloser Integer-Typ des Ergebnisses des Operators sizeof definiert .C Standard sagt in §17.7 / 2,
Und C ++ Standard sagt (über
cstddef
Header) in §18.1 / 3,Also ja, beide sind gleich; Der einzige Unterschied besteht darin, dass C ++
size_t
imstd
Namespace definiert .Bitte beachten Sie auch, dass in der obigen Zeile auch "mit den folgenden Änderungen" steht, auf die nicht Bezug genommen wird
size_t
. Es bezieht sich eher auf die neuen Ergänzungen (meistens), die C ++ in der Sprache (nicht in C vorhanden) vorgenommen hat und die ebenfalls im selben Header definiert sind.Wikipedia hat sehr gute Informationen über Reichweite und Speichergröße von size_t:
Und den Rest können Sie von dieser Seite auf Wikipedia lesen .
quelle
size_t
ohneusing namespace std;
oder zu sagenusing std::size_t;
. Die meisten Compiler erlauben dies jedoch, und der Standard erlaubt es ihnen ausdrücklich, dies zuzulassen (§D.5 / 3).<cstddef>
kann deklariert werden oder nicht::size_t
, sodass Sie sich nicht darauf verlassen können, dass er vorhanden ist oder fehlt, es sei denn, Sie enthalten ausdrücklich einen<stddef.h>
anderen Header aus der C-Bibliothek, der ihn garantiert deklariert.::size_t
ist zB in vorhanden<stddef.h>
, so dass Sie es nicht immer mit qualifizieren müssenstd::
.Ab C ++ 03 "17.4.3.1.4 Typen":
Und Fußnote 169:
quelle
std::T
definierten Varianten verlassen ?#include <stddef.h>
dannstd::size_t
möglicherweise verfügbar sind oder nicht. Wenn Sie#include <cstddef>
dannstd::size_t
verfügbar sind, abersize_t
möglicherweise nicht.std::
und der Absatz besagt, dass sie möglicherweise auch im Namespace der obersten Ebene definiert werden. Wenn dies der Fall ist, müssen sie instd::
und auf oberster Ebene identisch definiert werden. Die meisten Compiler enthalten nur den C-Header und importieren die Namen instd::
, sodass die Symbole in beiden definiert werden.std::
Varianten von Bezeichnern, die vom C-Ufer kommen. Ich bleibe bei<xxxxx.h>
den Standard-C-Headern - es war nie ein Problem. Also würde ich verwenden<stddef.h>
undsize_t
niemals darüber nachdenkenstd::size_t
; Tatsächlich fällt mir nie ein, dass es eine gibt (oder geben könnte)std::size_t
.std :: size_t ist in der Tat stddef.h ‚s size_t .
cstddef gibt Folgendes an:
... die vorherige Definition effektiv in den Standard-Namespace bringen.
quelle
<cstddef>
und erwarten zu bekommen::size_t
, aber wenn Sie einschließen, werden<stddef.h>
Sie bekommenstd::size_t
.<stddef.h>
wird nur Sie bekommen::size_t
.<cstddef>
Sie garantiert bekommenstd::size_t
und Sie könnten auch bekommen::size_t
(aber es ist nicht garantiert). Wenn Sie einschließen, werden<stddef.h>
Sie garantiert bekommen::size_t
und Sie könnten auch bekommenstd::size_t
(aber es ist nicht garantiert). In C ++ 03 war das anders, aber das war praktisch nicht umsetzbar und wurde als Fehler behoben.