Qual è la dimensione del vuoto?

Cosa produrrebbe questa affermazione?

void * p = (void*) malloc(sizeof(void)); 

Modifica: un’estensione alla domanda.

Se sizeof (void) restituisce 1 nel compilatore GCC, allora viene allocato 1 byte di memoria e il puntatore p punta a quel byte e p dovrebbe essere incrementato a 0x2346? Supponiamo che p sia 0x2345. Sto parlando di p e non * p.

Il tipo void non ha dimensioni; quello sarebbe un errore di compilazione. Per lo stesso motivo non puoi fare qualcosa del tipo:

 void n; 

MODIFICARE. Con mia sorpresa, fare sizeof(void) realtà compila in GNU C:

 $ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 1 

Tuttavia, in C ++ non:

 $ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out : In function 'int main()': :1: error: invalid application of 'sizeof' to a void type :1: error: 'printf' was not declared in this scope 

Se si utilizza GCC e non si utilizzano flag di compilazione che rimuovono estensioni specifiche del compilatore, quindi sizeof(void) è 1. GCC ha un’estensione non standard che lo fa.

In generale, void è un tipo incompleto e non è ansible utilizzare sizeof per i tipi incompleti.

Anche se void può stare in piedi per un tipo, non può effettivamente contenere un valore. Pertanto, non ha dimensioni in memoria. Ottenere la dimensione di un void non è definito.

Un puntatore void è semplicemente un costrutto linguistico che indica un puntatore alla memoria non tipizzata .

Prendendo la dimensione del vuoto è un’estensione GCC .

void non ha dimensioni. Sia in C che in C ++, l’espressione sizeof (void) non è valida.

In C, citando N1570 6.5.3.4 paragrafo 1:

L’operatore sizeof non deve essere applicato a un’espressione che ha un tipo di funzione o un tipo incompleto , al nome tra parentesi di un tale tipo o un’espressione che designa un membro del campo di bit.

(N1570 è una bozza dello standard ISO C del 2011).

void è un tipo incompleto. Questo paragrafo è un vincolo , il che significa che qualsiasi compilatore C conforms deve diagnosticare qualsiasi violazione di esso. (Il messaggio di diagnostica potrebbe essere un avviso non fatale).

Lo standard C ++ 11 ha una formulazione molto simile. Entrambe le edizioni sono state pubblicate dopo che è stata posta questa domanda, ma le regole risalgono allo standard ANSI C del 1989 e ai primi standard C ++. In effetti, la regola che il void è un tipo incompleto a cui sizeof non può essere applicata risale esattamente all’introduzione del void nella lingua.

gcc ha un’estensione che considera sizeof (void) come 1. gcc non è un compilatore C conforms per impostazione predefinita, quindi nella sua modalità predefinita non avvisa su sizeof (void) . Estensioni come questa sono consentite anche per compilatori C completamente conformi, ma la diagnostica è ancora necessaria.

sizeof() non può essere applicato a tipi incompleti. E void è un tipo incompleto che non può essere completato.

In C, sizeof(void) == 1 in GCC, ma sembra dipendere dal compilatore.

In C ++, ottengo:

 Nella funzione 'int main ()':
 Riga 2: errore: applicazione non valida di "sizeof" a un tipo di vuoto
 compilazione terminata a causa di -Wfatal-errors.

Alla seconda parte della domanda: nota sizeof (void *)! = Sizeof (void). Su un arco a 32 bit, sizeof (void *) è 4 byte, quindi p ++ verrà impostato di conseguenza. L’entity framework con cui viene incrementato un puntatore dipende dai dati a cui punta. Quindi, sarà aumentato di 1 byte.

mentre sizeof (void) forse non ha senso in sé, è importante quando stai facendo qualsiasi matematica con i puntatori.

per esempio.

  void *p; while(...) p++; 

Se sizeof (void) è considerato 1, allora funzionerà. Se sizeof (void) è considerato 0, si ottiene un ciclo infinito.

La maggior parte dei compilatori C ++ ha scelto di generare un errore di compilazione durante il tentativo di ottenere sizeof(void) .

Quando compila C, gcc non è conforms e ha scelto di definire sizeof(void) come 1. Può sembrare strano, ma ha una logica. Quando si esegue l’aritmetica del puntatore aggiungendo o rimuovendo un’unità si intende aggiungere o rimuovere l’object che punta alla dimensione. Quindi definire sizeof(void) come 1 aiuta a definire void* come puntatore al byte (indirizzo di memoria non tipizzato). Altrimenti si avrebbero comportamenti sorprendenti usando l’aritmetica del puntatore come p+1 == p when p è void* . Tale puntatore aritmetico sui puntatori void non è consentito in c ++ ma funziona bene quando si compila C con gcc.

Il metodo standard raccomandato sarebbe quello di usare char* per questo tipo di scopo (puntatore a byte).

Un’altra differenza simile tra C e C ++ quando si utilizza sizeof si verifica quando si definisce una struttura vuota come:

 struct Empty { } empty; 

Usando gcc come il mio compilatore C sizeof(empty) restituisce 0. Usando g ++ lo stesso codice restituirà 1.

Non sono sicuro di ciò che afferma gli standard C e C ++ su questo punto, ma credo che definire la dimensione di alcune strutture / oggetti vuoti aiuti con la gestione dei riferimenti per evitare che due riferimenti a diversi oggetti consecutivi, il primo sia vuoto, ottengano il stesso indirizzo. Se i riferimenti vengono implementati utilizzando i puntatori nascosti come spesso accade, assicurare un indirizzo diverso aiuterà a confrontarli.

Ma questo è semplicemente evitando un comportamento sorprendente (confronto tra maiuscole e minuscole di riferimenti) per introduzione un altro (oggetti vuoti, anche i POD consumano almeno 1 byte di memoria).