Es kommt darauf an, da size_t
ein implementierungsdefinierter vorzeichenloser Integraltyp ist.
Operationen mit einem size_t
werden daher Promotionen einführen, aber diese hängen davon ab, was size_t
tatsächlich ist, und welche anderen Typen in den Ausdruck tatsächlich involviert sind.
Wenn size_t
entsprechen einen unsigned short
(zB einen 16-Bit-Typen), dann
size_t foo = 1;
foo += 1;
würde (semantisch) fördern foo
zu einem int
, fügen 1
, und dann das Ergebnis konvertieren zurück zu size_t
zum Speichern in foo
. (Ich sage "semantisch", denn das ist die Bedeutung des Codes gemäß dem Standard. Ein Compiler kann die "Als-ob" -Regel anwenden - also tun, was er will, solange es den gleichen Nettoeffekt liefert).
Auf einer anderen Seite, wenn size_t
entsprechen einen long long unsigned
(zB einen 64-Bit unterzeichnet Typen), dann würde der gleiche Code 1
fördert von long long unsigned
Typ zu sein, das von foo
, auf den Wert addieren und das Ergebnis speichern zurück in foo
.
In beiden Fällen ist das Nettoergebnis gleich, es sei denn, ein Überlauf tritt auf. In diesem Fall gibt es keinen Überlauf, da sowohl int
als auch size_t
garantiert die Werte 1
und 2
darstellen können.
Wenn ein Überlauf auftritt (z. B. Hinzufügen eines größeren Integralwerts), kann das Verhalten variieren. Ein Überlauf eines vorzeichenbehafteten ganzzahligen Typs (z. B. int
) führt zu undefiniertem Verhalten. Überlauf eines unsigned
Integraltyps verwendet Modulo-Arithmetik.
Was den Code
size_t foo = SIZE_MAX;
foo += 1;
es möglich ist, die gleiche Art von Analyse zu tun.
Wenn size_t
entspricht einem unsigned short
dann foo
zu int
umgewandelt würden. Wenn int
einem signed short
entspricht, kann es nicht den Wert SIZE_MAX
darstellen, sodass die Konvertierung überläuft und das Ergebnis nicht definiert ist. Wenn int
einen größeren Bereich als short int
darstellen kann (z. B. entspricht es long
), wird die Konvertierung von foo
zu int
erfolgreich sein, die Erhöhung dieses Werts wird erfolgreich sein, und die Speicherung zurück zu size_t
wird Modulo-Arithmetik verwenden und das Ergebnis von 0
.
Wenn size_t
zu unsigned long
äquivalent ist, dann wird der Wert 1
unsigned long
zu konvertierenden hinzu, dass zu foo
Modulo-Arithmetik verwenden (das heißt ein Ergebnis von Null erzeugen), und das wird in foo
gespeichert werden.
Es ist möglich, ähnliche Analysen durchzuführen, wenn angenommen wird, dass size_t
tatsächlich andere vorzeichenlose ganzzahlige Typen sind.
Hinweis: In modernen Systemen ist eine size_t
, die die gleiche Größe oder kleiner als eine int
ist ungewöhnlich. Solche Systeme haben jedoch existiert (z. B. Microsoft- und Borland-C-Compiler, die auf 16-Bit-MS-DOS auf Hardware mit einer 80286-CPU abzielen). Es sind auch noch 16-Bit-Mikroprozessoren in Produktion, hauptsächlich zur Verwendung in eingebetteten Systemen mit geringerem Energieverbrauch und geringen Durchsatzanforderungen, und C-Compiler, die auf sie abzielen (z. B. Keil C166-Compiler, der auf die Infeon XE166-Mikroprozessorfamilie abzielt). [Hinweis: Ich hatte nie Grund, den Keil-Compiler zu verwenden, aber angesichts seiner Zielplattform wäre es keine Überraschung, wenn es einen 16-Bit size_t
unterstützt, der dieselbe Größe oder kleiner als der native int
-Typ auf dieser Plattform ist ].
Gute Frage. Erfahrungsgemäß ist "size_t" bei jeder Implementierung, die ich jemals verwendet habe, gleich groß oder größer als "int". Wenn wir uns darauf verständigen könnten (was wir natürlich nicht tun), würden wir bemerken, dass ein "int" die "natürliche" Größe für einen Integer-Typ bei jeder gegebenen Implementierung ist und daher keinen Sinn ergibt für 'size_t' kleiner als diese natürliche Größe. – user3386109
Beachten Sie, dass 'SIZE_MAX' nicht vom C89-Standard definiert wurde. –
Ist diese Frage über den aktuellen Standard oder C89? – 2501