2009-04-16 10 views
10

J'ai une structure sans membres (pour le moment) et je voudrais savoir s'il est possible de supprimer l'avertissement que je reçois:Structure vide dans C

warning: struct has no members 

Est-il possible d'ajouter un membre et gardez le sizeof la structure zéro? Toute autre solution?

+0

Pourquoi avez-vous besoin que la taille soit zéro? –

+1

Parce que j'ai une interface privée (dans laquelle j'ai ma structure de taille zéro parce que je n'implémente pas une certaine fonctionnalité) et une interface publique où certaines de mes structures privées deviennent opaques et doivent juste avoir la même taille que privée. – claf

+0

Mon système de construction vérifie la taille de la structure privée et crée la structure publique avec un "char _opaque [SIZEOF_PRIVATE_STRUCT]". – claf

Répondre

18

Dans c le comportement d'une structure vide est compilateur dépendants et C++ où il fait partie de la spécification (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.

en C, il est un peu plus sombre puisque la norme C99 a un langage qui implique que les structures vraiment vides ne sont pas permises (voir la réponse de TrayMan) mais que de nombreux compilateurs le permettent (eg gcc).

Étant donné que cela dépend du compilateur, il est peu probable que vous obteniez un code vraiment portable dans ce cas. En tant que tels moyens non portables pour supprimer l'avertissement peuvent être votre meilleur pari.

+0

Donc, il n'y a aucun moyen d'éviter de façon portative cet avertissement? (Par exemple, avoir un #pragma spécifique au compilateur aveC#ifdef par exemple) – claf

+0

De plus, pour GCC Diagnostic Pragmas: "Aussi, bien qu'il soit syntaxiquement valide de placer ces pragmas n'importe où dans vos sources, le seul emplacement supporté pour eux est avant toute donnée. ou les fonctions sont définies. " Ce qui signifie pour moi que je ne peux pas supprimer cet avertissement, ai-je raison? – claf

+1

La question concerne C, pas C++. –

1

Si vous n'êtes pas exigeant le respect « trop stricte », vous pouvez vous contenter de ceci:

struct empty { 
    char nothing[0]; 
}; 

C'est un GCC extension, cependant.

j'espérais que je serais en mesure d'utiliser la fonction C99 appelé « tableaux flexibles », a déclaré comme ceci:

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

mais cela ne fonctionne pas; ils exigent qu'il y ait au moins un membre struct normal en premier, ils ne peuvent pas être le seul membre.

+1

Eh bien, GCC accepte quand même des structures vides ... Apparemment avec une taille de 0. D'un autre coté, il échouera sur des structures vides ainsi qu'avec cette solution si le pédant est allumé (avertissements pédants + les transformant en erreurs). – Aconcagua

4

C99 standard est quelque peu ambiguë à ce sujet, mais semble dire qu'un struct vide devrait avoir non nul Taille.

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?

Non. FWIW, C++ autorise des structures vides mais sizeof() est toujours non nul pour une structure vide.

Any other solution?

Pas facile. Il vaut la peine de noter que les structures vides ne sont que légèrement supportées en C et interdites en C99.

Les structures vides sont supportées en C++ mais différents compilateurs les implémentent avec des résultats variables (pour les offsets sizeof et struct), surtout quand vous commencez à lancer l'héritage dans le mix.

18

si vous avez juste besoin le symbole struct pour les arguments de coulée et la fonction puis juste:

typedef struct _Interface Interface; 

cela va créer le symbole pour un type opaque.

+2

MERCI! J'essaie de tester mon projet sur différents compilateurs, et recevait une erreur de compilation bizarre dans Borland C++. Il me disait que cette fonction qui utilisait une structure vide n'était pas un membre de la classe dans laquelle il avait été déclaré. J'ai essayé de résoudre le problème pour Il s'est avéré que tout ce que je devais faire était de me débarrasser des parenthèses quand je déclarais la structure vide, comme vous le montrez, et cela fonctionne très bien .. Fils d'un b ----- Merci – leetNightshade

10

Techniquement, ce n'est même pas valide C.

TrayMan était un peu hors de son analyse, oui 6.2.6.1 dit:

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.

mais avec lien qui 6.2.5-20, qui dit:

— 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.

et maintenant vous pouvez conclure que les structures vont être un ou plusieurs octets car ils ne peuvent pas être vides. Votre code vous donne un avertissement, alors que le même code fait ne parviennent pas à compiler sur Visual Studio de Microsoft avec une erreur:

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

Donc, la réponse est non, il n'y a pas un moyen portable pour éviter cet avertissement, parce qu'il vous dit que vous violez les normes C. Vous devrez utiliser une extension spécifique au compilateur pour le supprimer.

0
struct zero_information { int:0; }; 

L'extrait de code ci-dessus donne une valeur non -Zero de sizeof(struct zero_information), mais il peut vous aider à obtenir ce que vous recherchez 100% de tout le stockage qui lui est allouée, est un rembourrage (seulement accessible par des hacks, bien que je ne me souvienne pas du haut de ma tête si l'accès au padding est un comportement indéfini).

+0

Tous les même comme dans mon commentaire pour la solution de unwind. – Aconcagua