Can sizeof return 0 (zero)

È ansible che l’operatore sizeof restituisca sempre 0 (zero) in C o C ++? Se è ansible, è corretto dal punto di vista degli standard?

In C ++ una class vuota o una struct ha una sizeof almeno 1 per definizione. Dallo standard C ++, 9/3 “Classi”: “Gli oggetti completi e i membri secondari membri di tipo class devono avere dimensioni diverse da zero.”

In C non è permessa una struttura vuota, tranne per estensione (o difetto nel compilatore).

Questa è una conseguenza della grammatica (che richiede che ci sia qualcosa all’interno delle parentesi graffe) insieme a questa frase da 6.7.2.1/7 “Strutturazione e identificatori di unione”: “Se la struct-declaration-list non contiene membri con nome, il comportamento è indefinito “.

Se una struttura a dimensione zero è consentita, allora è un’estensione di lingua (o un difetto nel compilatore). Ad esempio, in GCC l’estensione è documentata in “Strutture senza membri” , che dice:

GCC consente a una struttura C di non avere membri:

  struct empty { }; 

La struttura avrà dimensione zero. In C ++, le strutture vuote fanno parte del linguaggio. G ++ considera le strutture vuote come se avessero un singolo membro di tipo char .

sizeof non restituisce mai 0 in C e in C ++. Ogni volta che vedi la dimensione di valutazione a 0 è un bug / glitch / estensione di un compilatore specifico che non ha nulla a che fare con la lingua.

Ogni object in C deve avere un indirizzo univoco. In un altro modo, un indirizzo deve contenere non più di un object di un determinato tipo (in modo che il dereferenziazione del puntatore funzioni). Detto questo, considera una struttura “vuota”:

 struct emptyStruct {}; 

e, più specificamente, una serie di loro:

 struct emptyStruct array[10]; struct emptyStruct* ptr = &array[0]; 

Se gli oggetti erano effettivamente vuoti (cioè, se sizeof(struct emptyStruct) == 0 ), allora ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr , che non ha senso. A quale object si riferirebbe *ptr , ptr[0] o ptr[1] ?

Anche se una struttura non ha contenuto, il compilatore dovrebbe trattarlo come se fosse un byte di lunghezza per mantenere il principio “un indirizzo, un object”.

Le specifiche del linguaggio C (sezione A7.4.8) esprimono questo requisito come

quando applicato a una struttura o unione, il risultato (dell’operatore sizeof ) è il numero di byte nell’object, incluso qualsiasi riempimento richiesto per rendere l’object una matrice

Poiché un byte di riempimento deve essere aggiunto a un object “vuoto” affinché funzioni in un array, sizeof() deve pertanto restituire un valore di almeno 1 per qualsiasi input valido.

Modifica: la sezione A8.3 della specifica C chiama una struct senza un elenco di membri un tipo incompleto e la definizione di sizeof specifica gli stati (con enfasi aggiunta):

L’operatore (sizeof) non può essere applicato a un operando di tipo di funzione o di tipo incompleto o a un campo di bit.

Ciò implicherebbe che l’uso di sizeof su una struttura vuota sarebbe altrettanto valido quanto l’utilizzo su un tipo di dati che non è stato definito. Se il compilatore consente l’uso di strutture vuote, si tenga presente che l’uso di sizeof su di esse non è consentito secondo le specifiche C. Se il compilatore ti consente comunque di farlo, comprendi che questo comportamento non standard non funzionerà su tutti i compilatori; non fare affidamento su questo comportamento.

Modifica: guarda anche questa voce nelle FAQ di Bjarne Stroustrup.

Strutture vuote, come menziona l’ isbadawi . Anche gcc consente array di dimensioni 0 :

 int a[0]; sizeof(a); 

EDIT: Dopo aver visto il link MSDN, ho provato la struttura vuota in VS2005 e sizeof ha restituito 1. Non sono sicuro se si tratta di un bug VS o se la specifica è in qualche modo flessibile su quel genere di cose

a mio avviso, è meglio che sizeof restituisca 0 per una struttura di dimensione 0 (nello spirito di c). ma poi il programmatore deve stare attento quando prende la dimensione di una struttura vuota.

ma potrebbe causare un problema. quando viene definita una matrice di tali strutture, allora

& arr [1] == & arr [2] == & arr [0]

che li fa perdere le loro id quadro.

Immagino che questo non risponda direttamente alla tua domanda, se sia ansible o meno. bene che potrebbe essere ansible a seconda del compilatore. (come detto nella risposta di Michael sopra).

 typedef struct { int : 0; } x; x x1; x x2; 

In MSVC 2010 (/ Za / Wall):

 sizeof(x) == 4 &x1 != &x2 

Sotto GCC (-ansi -pedantic-Wall):

 sizeof(x) == 0 &x1 != &x2 

cioè Anche se sotto GCC ha dimensione zero, le istanze della struttura hanno indirizzi distinti.

ANSI C (C89 e C99 – Non ho guardato il C ++) dice “Dovrebbe essere ansible esprimere l’indirizzo di ogni singolo byte di un object in modo univoco.” Questo sembra ambiguo nel caso di un object di dimensioni zero, poiché probabilmente non ha byte.

Modifica: “Una dichiarazione del campo di bit senza dichiaratore, ma solo due punti e una larghezza, indica un campo di bit senza nome. Come caso speciale di questo, un campo di bit con una larghezza di 0 indica che non ci sono altri campi di bit deve essere inserito nell’unità in cui è stato inserito il campo di bit precedente, se presente. ”

Penso che non restituisca mai 0 in c, non sono permesse strutture vuote

Ecco un test, dove sizeof yields 0

 #include  void func(int i) { int vla[i]; printf ("%u\n",(unsigned)sizeof vla); } int main(void) { func(0); return 0; } 

Se hai questo:

 struct Foo {}; struct Bar { Foo v[]; } 

g++ -ansi restituisce sizeof (Bar) == 0. Come fa il compilatore clang & intel.

Tuttavia, questo non viene compilato con gcc. Ne deduco che è un’estensione C ++.

 struct Empty { } em; struct Zero { Empty a[0]; } zr; printf("em=%d\n", sizeof(em)); printf("zr=%d\n", sizeof(zr)); 

Risultato:

 em=1 zr=0