Was würde diese Aussage bringen?
void *p = malloc(sizeof(void));
Bearbeiten: Eine Erweiterung der Frage.
Wenn sizeof (void) im GCC-Compiler 1 ergibt, wird 1 Byte Speicher zugewiesen und der Zeiger p zeigt auf dieses Byte und würde p ++ auf 0x2346 erhöht werden? Angenommen, p war 0x2345. Ich spreche von p und nicht von * p.
c++
c
language-lawyer
sizeof
Lakshmi
quelle
quelle
Antworten:
Der Typ
void
hat keine Größe; das wäre ein Kompilierungsfehler. Aus dem gleichen Grund können Sie so etwas nicht tun:void n;
BEARBEITEN. Zu meiner Überraschung, tut
sizeof(void)
eigentlich nicht in GNU C kompilieren:$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 1
In C ++ ist dies jedoch nicht der Fall:
$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out <stdin>: In function 'int main()': <stdin>:1: error: invalid application of 'sizeof' to a void type <stdin>:1: error: 'printf' was not declared in this scope
quelle
sizeof (void)
ist eine Einschränkungsverletzung. Ein konformer C-Compiler (der gcc ist nicht standardmäßig) muss zumindest davor warnen und kann (und sollte IMHO sollte) dies ablehnen. Referenz: N1570 6.5.3.4p1 (void
ist ein unvollständiger Typ). Dies ist seit dem 1989 eingeführten Standard der Fallvoid
.void
existierte nicht, bevor es durch den ANSI C-Standard von 1989 eingeführt wurde, den gleichen Standard, dersizeof (void)
eine Einschränkungsverletzung verursachte.Wenn Sie GCC verwenden und keine Kompilierungsflags verwenden, mit denen compilerspezifische Erweiterungen entfernt werden,
sizeof(void)
ist dies 1. GCC verfügt über eine nicht standardmäßige Erweiterung , die dies tut.Im Allgemeinen
void
handelt es sich um einen unvollständigen Typ, und Sie können sizeof nicht für unvollständige Typen verwenden.quelle
-Wpointer-arith
ist impliziert durch-pedantic
. Ich habe es immer benutzt-pedantic
. :)Obwohl
void
es für einen Typ an Ort und Stelle stehen kann, kann es tatsächlich keinen Wert enthalten. Daher hat es keine Größe im Speicher. Das Abrufen der Größe von avoid
ist nicht definiert.Ein
void
Zeiger ist einfach ein Sprachkonstrukt, das einen Zeiger auf untypisierten Speicher bedeutet.quelle
void
hat keine Größe. Sowohl in C als auch in C ++ ist der Ausdrucksizeof (void)
ungültig.In C unter Angabe von N1570 6.5.3.4 Absatz 1:
(N1570 ist ein Entwurf der ISO C-Norm von 2011.)
void
ist ein unvollständiger Typ. Dieser Absatz ist eine Einschränkung , was bedeutet, dass jeder konforme C-Compiler eine Verletzung diagnostizieren muss. (Die Diagnosemeldung kann eine nicht tödliche Warnung sein.)Der C ++ 11-Standard hat einen sehr ähnlichen Wortlaut. Beide Ausgaben wurden veröffentlicht, nachdem diese Frage gestellt wurde, aber die Regeln gehen auf den ANSI C-Standard von 1989 und die frühesten C ++ - Standards zurück. Tatsächlich reicht die Regel,
void
die ein unvollständiger Typ ist, auf densizeof
möglicherweise nicht angewendet wird, genau bis zur Einführungvoid
in die Sprache zurück.gcc hat eine Erweiterung , die
sizeof (void)
als 1 behandelt wird . gcc ist standardmäßig kein konformer C-Compiler, daher wird im Standardmodus nicht gewarntsizeof (void)
. Erweiterungen wie diese sind auch für vollständig konforme C-Compiler zulässig, die Diagnose ist jedoch weiterhin erforderlich.quelle
sizeof(void) == 1
Konsistenz mit Zeigerarithmetik aufvoid
Zeiger zugelassen haben, das ist auch eine gcc-Erweiterung . Unter Berufung auf ihre Dokumentation :A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
. Trotzdem sollte für C standardmäßig eine Diagnosemeldung vorhanden sein, wie es der Standard erfordert.-std=c11 -pedantic
. Mit solchen Optionen wird die erforderliche Diagnose ausgegeben.Die Größe von void ist eine GCC-Erweiterung .
quelle
sizeof()
kann nicht auf unvollständige Typen angewendet werden. Undvoid
ist ein unvollständiger Typ, der nicht abgeschlossen werden kann.quelle
In C,
sizeof(void) == 1
in GCC, aber dies scheint von Ihrem Compiler abzuhängen.In C ++ bekomme ich:
quelle
Zum 2. Teil der Frage: Beachten Sie, dass sizeof (void *)! = Sizeof (void). In einem 32-Bit-Bogen beträgt sizeof (void *) 4 Byte, daher wird p ++ entsprechend festgelegt. Der Betrag, um den ein Zeiger inkrementiert wird, hängt von den Daten ab, auf die er zeigt. Es wird also um 1 Byte erhöht.
quelle
T*
wird um inkrementiertsizeof(T)
(und nichtsizeof(T*)
, was fast immer gleich wäre, außer vielleicht für Funktionszeiger), wenn er inkrementiert wird. Die Ausnahme ist natürlichvoid
(und wieder ist die Ausnahme, wenn die GCC-Erweiterungen aktiviert sind).void*
Zeiger zeigt, 1 Byte beträgt?sizeof (void)
ist eine Einschränkungsverletzung. (Eine gcc-Erweiterung behandelt es als 1.)Während sizeof (void) an sich vielleicht keinen Sinn ergibt, ist es wichtig, wenn Sie Zeiger rechnen.
z.B.
void *p; while(...) p++;
Wenn sizeof (void) als 1 betrachtet wird, funktioniert dies. Wenn sizeof (void) als 0 betrachtet wird, treffen Sie eine Endlosschleife.
quelle
unsigned char*
.char
wird nicht garantiert, dass 1 Byte vorhanden ist. Ich habe an einem System gearbeitet, das es auf 32 Bit eingestellt hat.char
garantiert 1 Byte. Wenn Sie auf einem 32-Bit-char
System gearbeitet haben, beträgt ein Byte auf diesem System 32 Bit (CHAR_BIT == 32
). So definiert der C-Standard "Byte". C - Standard, 6.5.3.4 Absätze 2 und 4: „Dersizeof
Operator liefert die Größe (in Bytes) des Operanden [...] , wenn.sizeof
Wird auf einen Operanden angewandt , die Aktivität hatchar
,unsigned char
odersigned char
, (oder eine qualifizierte Version davon) das Ergebnis ist 1. "Die meisten C ++ - Compiler haben sich entschieden, beim Abrufen einen Kompilierungsfehler auszulösen
sizeof(void)
.Beim Kompilieren von C ist gcc nicht konform und wird
sizeof(void)
als 1 definiert . Es mag seltsam aussehen, hat aber eine Begründung. Wenn Sie eine Zeigerarithmetik ausführen, bedeutet das Hinzufügen oder Entfernen einer Einheit das Hinzufügen oder Entfernen des Objekts, auf das die Größe zeigt. Das Definierensizeof(void)
als 1 hilft also beim Definierenvoid*
als Zeiger auf das Byte (untypisierte Speicheradresse). Andernfalls würden Sie überraschende Verhaltensweisen haben, wenn Sie Zeigerarithmetik wiep+1 == p when
p verwendenvoid*
. Eine solche Zeigerarithmetik für leere Zeiger ist in c ++ nicht zulässig, funktioniert jedoch gut, wenn C mit gcc kompiliert wird.Die empfohlene Standardmethode wäre die Verwendung
char*
für diesen Zweck (Zeiger auf Byte).Ein weiterer ähnlicher Unterschied zwischen C und C ++ bei Verwendung von sizeof tritt auf, wenn Sie eine leere Struktur wie folgt definiert haben:
struct Empty { } empty;
Wenn Sie gcc als meinen C-Compiler verwenden, wird
sizeof(empty)
0 zurückgegeben. Wenn Sie g ++ verwenden, gibt derselbe Code 1 zurück.Ich bin nicht sicher, was in diesem Punkt sowohl C- als auch C ++ - Standards angibt, aber ich glaube, dass das Definieren der Größe einiger leerer Strukturen / Objekte bei der Referenzverwaltung hilft, um zu vermeiden, dass zwei Verweise auf unterschiedliche aufeinanderfolgende Objekte, von denen das erste leer ist, die erhalten die gleiche Anschrift. Wenn Referenzen mithilfe versteckter Zeiger implementiert werden, wie dies häufig der Fall ist, hilft das Sicherstellen einer anderen Adresse beim Vergleichen.
Dies vermeidet jedoch lediglich ein überraschendes Verhalten (Vergleich von Referenzen in Eckfällen), indem ein anderes eingeführt wird (leere Objekte, selbst PODs verbrauchen mindestens 1 Byte Speicher).
quelle
sizeof(void)
ist in C nicht wie in C ++ definiert. GCC stimmt in diesem Punkt einfach nicht überein, und die Zeigerarithmetik fürvoid
Zeiger ist ebenfalls einfach nicht definiert -void* p; p++;
ist ungültig. Sogar GCC gibt Ihnen beim Kompilieren mit dem-pedantic
Flag eine Warnung . Und Sie irren sich auch über das Standardverhalten von GCC für C ++: Standardmäßig wird dies als Fehler behandelt .struct
Definition ein Syntaxfehler. Die Unterstützung von gcc ist eine Erweiterung. Sie können in C ++ gültig sein; Ich bin mir nicht sicher.