Ich bin verwirrt mit size_t
in C. Ich weiß, dass es vom sizeof
Bediener zurückgegeben wird. Aber was genau ist das? Ist es ein Datentyp?
Angenommen, ich habe eine for
Schleife:
for(i = 0; i < some_size; i++)
Soll ich verwenden int i;
oder size_t i;
?
int
ifsome_size
ist signiert,size_t
wenn es nicht signiert ist.int i
möglicherweise nicht aus, um ein großes Array zu adressieren.size_t i
Wenn Sie also verwenden , können Sie mehr Indizes adressieren. Selbst wenn Sie ein riesiges Array haben, sollte dies kein Problem sein.size_t
ist ein Datentyp: normalerweise aunsigned long int
, dies hängt jedoch von Ihrem System ab.Antworten:
Aus Wikipedia :
Folglich
size_t
ist ein Typ garantiert, der jeden Array-Index enthält.quelle
size_t
ist für Objekte im Speicher. Der C-Standard definiert nicht einmalstat()
oderoff_t
(das sind POSIX-Definitionen) oder irgendetwas, das mit Festplatten oder Dateisystemen zu tun hat - er stoppt sich beiFILE
Streams. Die Verwaltung des virtuellen Speichers unterscheidet sich in Bezug auf die Größenanforderungen grundlegend von Dateisystemen und der Dateiverwaltung. Daheroff_t
ist die Erwähnung hier irrelevant.size_t
als den Typ des Ergebnisses dessizeof
Operators (ungefähr 7.17p2<stddef.h>
). In Abschnitt 6.5 wird genau erläutert, wie C-Ausdrücke funktionieren (6.5.3.4 fürsizeof
). Da Sie keinesizeof
Datenträgerdatei anwenden können (hauptsächlich, weil C nicht einmal definiert, wie Datenträger und Dateien funktionieren), besteht kein Raum für Verwirrung. Mit anderen Worten, beschuldigen Sie Wikipedia (und diese Antwort für das Zitieren von Wikipedia und nicht des tatsächlichen C-Standards).size_t
ist ein vorzeichenloser Typ. Es können also keine negativen Werte (<0) dargestellt werden. Sie verwenden es, wenn Sie etwas zählen, und sind sicher, dass es nicht negativ sein kann. Gibt beispielsweise astrlen()
zurück,size_t
da die Länge eines Strings mindestens 0 sein muss.Wenn in Ihrem Beispiel Ihr Schleifenindex immer größer als 0 sein soll, ist die Verwendung
size_t
eines anderen vorzeichenlosen Datentyps möglicherweise sinnvoll .Wenn Sie ein
size_t
Objekt verwenden, müssen Sie sicherstellen, dass Sie in allen verwendeten Kontexten, einschließlich der Arithmetik, nicht negative Werte wünschen. Nehmen wir zum Beispiel an, Sie haben:und Sie möchten den Unterschied der Längen von
str2
und findenstr1
. Du kannst nicht tun:Dies liegt daran, dass der zugewiesene Wert
diff
immer eine positive Zahl ist, auch wenns2 < s1
die Berechnung mit vorzeichenlosen Typen durchgeführt wird. In diesem Fall ist es je nach Anwendungsfall möglicherweise besser,int
(oderlong long
) fürs1
und zu verwendens2
.Es gibt einige Funktionen in C / POSIX, die verwendet werden könnten / sollten
size_t
, aber aus historischen Gründen nicht. Zum Beispiel sollte der zweite Parameterfgets
idealerweise seinsize_t
, ist es aberint
.quelle
size_t
? 2) Warum sollte ich sosize_t
etwas vorziehenunsigned int
?size_t
istsizeof(size_t)
. Der C-Standard garantiert, dassSIZE_MAX
mindestens 65535 vorliegt. Diessize_t
ist der vomsizeof
Operator zurückgegebene Typ und wird in der Standardbibliothek verwendet (z. B.strlen
Rückgabesize_t
). Wie Brendan sagte,size_t
muss nicht dasselbe sein wieunsigned int
.size_t
wird garantiert ein nicht signierter Typ.s2 - s1
überläuftint
, ist das Verhalten undefiniert.size_t
ist ein Typ, der jeden Array-Index enthalten kann.Abhängig von der Implementierung kann es sich um Folgendes handeln:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
So
size_t
ist instddef.h
meiner Maschine definiert:quelle
typedef unsigned long size_t
ist der Compiler abhängig. Oder schlagen Sie vor, dass es immer so ist?unsigned long
ist 32-Bit,size_t
ist 64-Bit.size_t
ist keine Variable. Dies ist ein Typ, den Sie verwenden können, wenn Sie die Größe eines Objekts im Speicher darstellen möchten.size_t
Stimmt es, dass auf einem 32-Bit-Computer immer 32 Bit und 64 Bit ebenfalls vorhanden sind?Wenn Sie der empirische Typ sind ,
Ausgabe für Ubuntu 14.04 64-Bit GCC 4.8:
Beachten Sie, dass
stddef.h
dies von GCC bereitgestellt wird und nicht untersrc/gcc/ginclude/stddef.h
GCC 4.2 angezeigt wird.Interessante C99 Auftritte
malloc
nimmtsize_t
als Argument, so bestimmt es die maximale Größe, die zugewiesen werden kann.Und da wird es auch von zurückgegeben
sizeof
, begrenzt es meiner Meinung nach die maximale Größe eines Arrays.Siehe auch: Was ist die maximale Größe eines Arrays in C?
quelle
size_t
ist , zumindest in einer beliebten Linux-Distribution.Die Manpage für types.h sagt:
quelle
Da es noch niemand erwähnt hat, besteht die primäre sprachliche Bedeutung
size_t
darin, dass dersizeof
Operator einen Wert dieses Typs zurückgibt. Ebenso ist die Hauptbedeutung von,ptrdiff_t
dass das Subtrahieren eines Zeigers von einem anderen einen Wert dieses Typs ergibt. Bibliotheksfunktionen, die dies akzeptieren, tun dies, weil solche Funktionen auf Objekten, auf denen solche Objekte vorhanden sein könnten, mit Objekten arbeiten können, deren Größe UINT_MAX überschreitet, ohne dass Aufrufer gezwungen werden, Code zu verschwenden, der auf Systemen mit dem größeren Typ einen Wert über "unsigned int" übergibt würde für alle möglichen Objekte ausreichen.quelle
malloc()
. Persönlich würde ich gern noch gesehen Versionen habe , die Argumente vom Typ nehmenint
,long
undlong long
, mit einigen Implementierungen fördern kürzeren Typen und andere Implementierung zBlmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}
[auf einigen Plattformen zu nennenimalloc(123)
wäre billiger als ein Anruflmalloc(123);
, und sogar auf einer Plattform , wosize_t
16 Bits, Code, der die Größe zuweisen möchte, die in einem "langen" Wert berechnet wurde ...Um zu erklären, warum
size_t
es existieren musste und wie wir hierher kamen:In pragmatischen Begriffen
size_t
undptrdiff_t
bei einer 64-Bit-Implementierung mit einer Breite von 64 Bit, bei einer 32-Bit-Implementierung mit einer Breite von 32 Bit usw. garantiert. Sie konnten keinen vorhandenen Typ dazu zwingen, dies auf jedem Compiler zu bedeuten, ohne den alten Code zu beschädigen.Ein
size_t
oderptrdiff_t
ist nicht unbedingt dasselbe wie einintptr_t
oderuintptr_t
. Sie waren anders auf bestimmte Architekturen , die noch in Gebrauch waren , alssize_t
undptrdiff_t
wurden dem Standard - in den späten 80er Jahren hinzugefügt und veralten , wenn C99 viele neue Arten hinzugefügt , aber noch nicht gegangen (wie 16-Bit - Windows). Das x86 im 16-Bit-geschützten Modus hatte einen segmentierten Speicher, in dem das größtmögliche Array oder die größtmögliche Struktur nur 65.536 Byte groß sein konnte, einfar
Zeiger jedoch 32 Bit breit und breiter als die Register sein musste. Auf denenintptr_t
wäre aber 32 Bit breit gewesensize_t
undptrdiff_t
könnte 16 Bit breit sein und in ein Register passen. Und wer wusste, welche Art von Betriebssystem in Zukunft geschrieben werden könnte? Theoretisch bietet die i386-Architektur ein 32-Bit-Segmentierungsmodell mit 48-Bit-Zeigern, das noch kein Betriebssystem verwendet hat.Der Typ eines Speicherversatzes könnte nicht sein,
long
weil viel zu viel Legacy-Code davon ausgeht, dass erlong
genau 32 Bit breit ist. Diese Annahme wurde sogar in die UNIX- und Windows-APIs integriert. Leider gingen viele andere Legacy-Codes auch davon aus, dass along
breit genug ist, um einen Zeiger, einen Datei-Offset, die Anzahl der Sekunden, die seit 1970 vergangen sind, usw. aufzunehmen. POSIX bietet jetzt eine standardisierte Möglichkeit, die letztgenannte Annahme anstelle der ersteren als wahr zu erzwingen, aber es ist auch keine tragbare Annahme zu treffen.Es konnte nicht sein,
int
dass nur eine winzige Handvoll Compiler in den 90er Jahrenint
64 Bit breit waren. Dann wurden sie wirklich komisch, indem sielong
32 Bit breit hielten . Die nächste Überarbeitung des Standards erklärte es für illegalint
, breiter als zu seinlong
, ist aberint
auf den meisten 64-Bit-Systemen immer noch 32 Bit breit.Es konnte nicht sein
long long int
, was ohnehin später hinzugefügt wurde, da dieses selbst auf 32-Bit-Systemen mindestens 64 Bit breit war.Es wurde also ein neuer Typ benötigt. Selbst wenn dies nicht der Fall wäre, bedeuteten all diese anderen Typen etwas anderes als einen Versatz innerhalb eines Arrays oder Objekts. Und wenn es eine Lehre aus dem Fiasko der 32-zu-64-Bit-Migration gab, sollte genau angegeben werden, welche Eigenschaften ein Typ haben muss, und nicht eine, die in verschiedenen Programmen unterschiedliche Bedeutungen hat.
quelle
size_t
undptrdiff_t
bei einer 64-Bit-Implementierung sind sie garantiert 64 Bit breit" usw. Die Garantie ist überbewertet. Der Bereich vonsize_t
wird hauptsächlich von der Speicherkapazität der Implementierung bestimmt. "eine n-Bit-Implementierung" ist hauptsächlich die native Prozessorbreite von ganzen Zahlen. Sicherlich verwenden viele Implementierungen eine Speichergröße und Prozessorbusbreite ähnlicher Größe, aber es gibt breite native Ganzzahlen mit wenig Speicher oder schmale Prozessoren mit viel Speicher, die diese beiden Implementierungseigenschaften auseinander treiben.size_t
undint
sind nicht austauschbar. Zum Beispielsize_t
ist Linux unter 64-Bit 64-Bit groß (dhsizeof(void*)
), aberint
32-Bit.Beachten Sie auch, dass dies
size_t
nicht signiert ist. Wenn Sie eine signierte Version benötigen, gibt es diesessize_t
auf einigen Plattformen und sie wäre für Ihr Beispiel relevanter.In der Regel würde ich mit vorschlagen
int
für die meisten allgemeinen Fälle und nur verwendensize_t
/ssize_t
wenn es ein besonderer Bedarf dafür ist (mitmmap()
zum Beispiel).quelle
Wenn Sie bei 0 beginnen und nach oben gehen, verwenden Sie im Allgemeinen immer einen vorzeichenlosen Typ, um einen Überlauf zu vermeiden, der Sie in eine negative Wertsituation führt. Dies ist von entscheidender Bedeutung, denn wenn Ihre Array-Grenzen zufällig kleiner als das Maximum Ihrer Schleife sind, Ihr Schleifenmaximum jedoch größer als das Maximum Ihres Typs ist, werden Sie negativ umbrochen und es kann zu einem Segmentierungsfehler (SIGSEGV) kommen ). Verwenden Sie daher im Allgemeinen niemals int für eine Schleife, die bei 0 beginnt und nach oben geht. Verwenden Sie eine nicht signierte.
quelle
size_t ist ein vorzeichenloser ganzzahliger Datentyp. Auf Systemen, die die GNU C-Bibliothek verwenden, ist dies int ohne Vorzeichen oder long int ohne Vorzeichen. size_t wird üblicherweise für die Array-Indizierung und Schleifenzählung verwendet.
quelle
size_t oder ein beliebiger vorzeichenloser Typ kann als Schleifenvariable verwendet werden, da Schleifenvariablen normalerweise größer oder gleich 0 sind.
Wenn wir ein size_t- Objekt verwenden, müssen wir sicherstellen, dass in allen verwendeten Kontexten, einschließlich der Arithmetik, nur nicht negative Werte gewünscht werden. Zum Beispiel würde folgendes Programm definitiv das unerwartete Ergebnis liefern:
quelle
size_t
ist ein vorzeichenloser Integer-Datentyp, der nur 0 und mehr als 0 Integer-Werte zuweisen kann. Es misst Bytes der Größe eines Objekts und wird vomsizeof
Operator zurückgegeben.const
ist die Syntaxdarstellung vonsize_t
, aber ohne dassconst
Sie das Programm ausführen können.size_t
Wird regelmäßig für die Array-Indizierung und Schleifenzählung verwendet. Wenn der Compiler ist32-bit
, würde es funktionierenunsigned int
. Wenn der Compiler ist64-bit
, würde es auch funktionierenunsigned long long int
. Dort für maximale Größesize_t
je nach Compilertyp.size_t
definiert bereits auf<stdio.h>
Header - Datei, aber es kann auch durch definieren<stddef.h>
,<stdlib.h>
,<string.h>
,<time.h>
,<wchar.h>
Header.const
)Ausgabe -:
size = 800
const
)Ausgabe -:
size = 800
quelle
Nach meinem Verständnis
size_t
handelt es sich um eineunsigned
Ganzzahl, deren Bitgröße groß genug ist, um einen Zeiger auf die native Architektur aufzunehmen.Damit:
quelle
size_t
. Einige Beispiele: C-Compiler im x86-Real-Modus können 32 BitFAR
oderHUGE
Zeiger haben, aber size_t beträgt immer noch 16 Bit. Ein weiteres Beispiel: Watcom C hatte früher einen speziellen Fettzeiger für erweiterten Speicher, der 48 Bit breit war, abersize_t
nicht. Auf einem eingebetteten Controller mit Harvard-Architektur haben Sie auch keine Korrelation, da beide unterschiedliche Adressräume betreffen.size_t