2009-04-16 18 views
10

Ho una struttura senza membri (per il momento) e vorrei sapere se è possibile eliminare l'avviso ottengo:struttura vuota in C

warning: struct has no members 

E 'possibile aggiungere un membro e mantieni lo struct zero allo sizeof? Qualche altra soluzione?

+0

Perché è necessario che la dimensione sia zero? –

+1

Perché ho un'interfaccia privata (in cui ho la mia struct zero size perché non implemento una determinata functionnality) e un'interfaccia pubblica in cui alcune delle mie strutture private diventano opache e devono avere le stesse dimensioni di quelle private. – claf

+0

Il mio sistema di build controlla la dimensione della struct privata e crea la struttura pubblica con un "char _opaque [SIZEOF_PRIVATE_STRUCT]". – claf

risposta

18

In c il comportamento di una struttura vuota è compilatore dipendente rispetto C++ dove è parte della specifica (explanations here)

C++
A class with an empty sequence of members and base class objects is an empty class. Complete objects and member subobjects of an empty class type shall have nonzero size.

in C è piuttosto più torbida poiché lo standard C99 ha un linguaggio che implica che le strutture veramente vuote non sono permesse (vedi la risposta di TrayMan) ma molti compilatori lo permettono (es. gcc).

Poiché questo è dipendente dal compilatore, è improbabile che in questo caso si ottenga un codice veramente portatile. Come tali modi non portabili per sopprimere l'avvertimento potrebbe essere la soluzione migliore.

+0

Quindi non c'è modo di evitare questo avviso? (Altrimenti, per esempio, con #pragma di un compilatore utilizzando #ifdef) – claf

+0

Inoltre, per la direttiva di diagnostica GCC: "Inoltre, mentre è sintatticamente valido mettere questi praga in qualsiasi punto delle fonti, l'unica posizione supportata per loro è prima di qualsiasi dato o le funzioni sono definite. " Il che significa per me che non posso sopprimere questo avvertimento, ho ragione? – claf

+1

La domanda riguarda C, non C++. –

1

Se non sei richiedono "troppo severo" l'adesione, si potrebbe ottenere via con questo:

struct empty { 
    char nothing[0]; 
}; 

Questo è un GCC extension, però.

Ero un po 'sperando che sarei in grado di utilizzare la funzione di C99 chiamata "matrici flessibili", ha dichiarato in questo modo:

struct empty99 
{ 
    char nothing[]; // This is a C99 "flexible array". 
}; 

ma che non funziona; richiedono che ci sia almeno un normale membro della struttura per primo, non possono essere l'unico membro.

+1

Bene, GCC accetta comunque strutture vuote ... Apparentemente con una dimensione pari a 0. D'altra parte, fallirà su strutture vuote e con questa soluzione se pedantic viene attivato (avvertimenti pedanti + trasformandoli in errori). – Aconcagua

4

C99 standard una certa ambiguità su questo, ma sembra dire che uno struct vuoto dovrebbe avere non-zero dimensione.

6.2.6.1 Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.

2

Is it possible to add a member and keep the sizeof the struct zero?

Nope. FWIW, C++ consente le strutture vuote ma sizeof() è sempre diverso da zero per una struttura vuota.

Any other solution?

Non facile. Vale la pena notare che le strutture vuote sono solo parzialmente supportate in C e non permesse in C99.

Le strutture vuote sono supportate in C++, ma diversi compilatori le implementano con risultati variabili (per offset sizeof e struct), soprattutto quando si inizia a lanciare l'ereditarietà nel mix.

18

se avete solo bisogno il simbolo struct per la fusione e la funzione argomenti poi basta:

typedef struct _Interface Interface; 

questo creerà il simbolo di un tipo opaco.

+2

GRAZIE! Sto provando a testare il mio progetto su diversi compilatori, e ricevevo uno strano errore di compilazione in Borland C++. Mi diceva che questa funzione che utilizzava una struttura vuota non era un membro della classe in cui era stata dichiarata. Ho cercato di risolvere il problema per le ultime 2,5 ore: si è scoperto che tutto ciò che dovevo fare era eliminare le parentesi quando dichiaro la struttura vuota, come si mostra, e funziona bene. Figlio di un b ----. Grazie !! – leetNightshade

10

Tecnicamente non è nemmeno valido C.

TrayMan era un po 'fuori nella sua analisi, sì 6.2.6.1 dice:

Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined.

ma legame che con 6.2.5-20, che dice:

— A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.

e ora si può Concludo che le strutture saranno uno o più byte perché non possono essere vuoti. Il vostro codice che sta dando un avvertimento, mentre lo stesso codice sarà effettivamente riuscire a compilare su Visual Studio di Microsoft con un errore:

error C2016: C requires that a struct or union has at least one member

Quindi la risposta breve è no, non c'è un modo portatile per evitare questo avviso, perché ti sta dicendo che stai violando gli standard C. Dovrai usare un'estensione specifica del compilatore per sopprimerla.

0
struct zero_information { int:0; }; 

Il frammento di codice di cui sopra produrrà un non valore -Zero da sizeof(struct zero_information), ma potrebbe aiutare a ottenere ciò che si cerca, come il 100% di tutta la memoria assegnata per esso, è imbottitura (solo accessibile tramite hack, anche se non ricordo da cima a capo se l'inserimento del padding è un comportamento indefinito).

+0

stesso come nel mio commento per la soluzione di unwind. – Aconcagua