Es gibt einen alten Beitrag, der nach einem Konstrukt fragt, für das er zurückkehren sizeof
würde 0
. Es gibt einige Highscore-Antworten von Benutzern mit hohem Ansehen, die besagen, dass standardmäßig kein Typ oder keine Variable eine Größe von 0 haben kann. Und ich stimme dem zu 100% zu.
Es gibt jedoch diese neue Antwort, die diese Lösung darstellt:
struct ZeroMemory {
int *a[0];
};
Ich wollte gerade abstimmen und es kommentieren, aber die Zeit, die ich hier verbracht habe, hat mich gelehrt, selbst die Dinge zu überprüfen, bei denen ich mir zu 100% sicher bin. Also ... zu meiner Überraschung beide gcc
und clang
zeigen die gleichen Ergebnisse : sizeof(ZeroMemory) == 0
. Darüber hinaus ist die Größe einer Variablen 0
:
ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...
Was ...?
Wie ist das möglich?
c++
language-lawyer
sizeof
Bolov
quelle
quelle
Antworten:
Bevor C standardisiert wurde, hätten viele Compiler keine Schwierigkeiten gehabt, mit Typen mit der Größe Null umzugehen, solange der Code nie versucht hätte, einen Zeiger auf einen Typ mit der Größe Null von einem anderen zu subtrahieren. Solche Typen waren nützlich, und ihre Unterstützung war einfacher und billiger als das Verbot. Andere Compiler haben sich jedoch entschlossen, solche Typen zu verbieten, und einige statische Assertionscodes haben sich möglicherweise auf die Tatsache gestützt, dass sie kreischen würden, wenn Code versuchen würde, ein Array mit der Größe Null zu erstellen. Die Autoren des Standards standen vor der Wahl:
Ermöglichen Sie Compilern, stillschweigend Array-Deklarationen mit der Größe Null zu akzeptieren, selbst wenn der Zweck solcher Deklarationen darin besteht, eine Diagnose auszulösen und die Kompilierung abzubrechen, und verlangen Sie, dass alle Compiler solche Deklarationen akzeptieren (wenn auch nicht unbedingt stillschweigend), um Objekte mit der Größe Null zu erzeugen .
Ermöglichen Sie Compilern, Array-Deklarationen mit der Größe Null stillschweigend zu akzeptieren, selbst wenn der Zweck solcher Deklarationen darin besteht, eine Diagnose- und Abbruchkompilierung auszulösen, und Compilern, die auf solche Deklarationen stoßen, die Kompilierung entweder abzubrechen oder nach Belieben fortzusetzen.
Erfordern, dass Implementierungen eine Diagnose ausgeben, wenn Code ein Array mit der Größe Null deklariert, aber dann Implementierungen erlauben, die Kompilierung entweder abzubrechen oder nach Belieben fortzusetzen (mit welcher Semantik sie dies für richtig halten).
Die Autoren des Standards entschieden sich für # 3. Folglich werden Array-Deklarationen mit der Größe Null von der Standard- "Erweiterung" berücksichtigt, obwohl solche Konstrukte weitgehend unterstützt wurden, bevor der Standard sie verbot.
Der C ++ - Standard erlaubt das Vorhandensein leerer Objekte. Um jedoch zu ermöglichen, dass die Adressen leerer Objekte als Token verwendet werden können, muss sie eine Mindestgröße von 1 haben. Für ein Objekt ohne Mitglieder muss eine Größe von 1 vorhanden sein 0 würde somit den Standard verletzen. Wenn ein Objekt jedoch Elemente mit der Größe Null enthält, stellt der C ++ - Standard keine Anforderungen an die Verarbeitung, außer dass ein Programm, das eine solche Deklaration enthält, eine Diagnose auslösen muss. Da der meiste Code, der solche Deklarationen verwendet, erwartet, dass die resultierenden Objekte eine Größe von Null haben, besteht das nützlichste Verhalten für Compiler, die solchen Code erhalten, darin, sie so zu behandeln.
quelle
struct polygon { int count; POINT sides[0];}; struct { struct polygon poly; POINT pts[3]; } myTriangle = { {3}, {{1,1},{2,2},{2,1} };
. Man müsste vorsichtig sein, um sicherzustellen, dass die Ausrichtung keine Probleme verursacht, aber man könnte Objekte mit statischer Dauer unterschiedlicher Größe haben, die austauschbar verarbeitet werden könnten.Wie von Jarod42 hervorgehoben, handelt es sich bei Arrays mit der Größe Null nicht um Standard-C ++, sondern um GCC- und Clang-Erweiterungen.
Das Hinzufügen
-pedantic
erzeugt diese Warnung:Ich vergesse immer, dass
std=c++XX
(stattstd=gnu++XX
) nicht alle Erweiterungen deaktiviert werden.Dies erklärt das
sizeof
Verhalten immer noch nicht . Aber zumindest wissen wir, dass es nicht Standard ist ...quelle
sizeof(int*)
(ich nehme an): coliru.stacked-crooked.com/a/e9a3038bf587b65csizeof
für diesen Typ ergibt, nicht. Das Verhalten ist daher eine Entscheidung der Compiler-Entwickler.ZeroMemory* z = (ZeroMemory*)malloc(sizeof(ZeroMemory) + 2 * sizeof(int*)); z.a[1] = new int{1}; /* or whatever, just use indices into a to access dynamic memory after the previous members (in this case: none) */
natürlich, dass dies nicht standardkompatibel ist! (Dies kann zum einfachen Parsen von Netzwerknachrichten mit dynamischer Länge verwendet werden, indem beispielsweise in eine Struktur umgewandelt wird.)In C ++ ist ein Array mit der Größe Null unzulässig.
ISO / IEC 14882: 2003 8.3.4 / 1:
Für g ++ muss das
-pedantic
Flag eine Warnung für ein Array mit der Größe Null ausgeben.quelle
Arrays mit der Länge Null sind eine Erweiterung von GCC und Clang. Das Anwenden
sizeof
auf Arrays mit der Länge Null wird mit Null bewertet .Eine C ++ - Klasse (leer) kann keine Größe
0
haben. Beachten Sie jedoch, dass die KlasseZeroMemory
nicht leer ist. Es hat ein benanntes Mitglied mit Größe0
und die Anwendungsizeof
gibt Null zurück.quelle
0
, aber eine nicht leere Klasse kann Größe haben0
... das macht nicht viel Sinn. Aber ich denke, dies ist die Art von widersprüchlichem Randfall, den Sie bei nicht standardmäßigen Erweiterungen erhalten.0
. In diesem speziellen Fall hat das Mitglied von struct it self die Größe 0 und dies macht die Größe von struct 0. Ich weiß, dass es verwirrend ist, aber ich habe mein Bestes versucht, es zu erklären.