8
votes

Typedef et struct dans les fichiers C et H

J'utilise le code suivant pour créer diverses struct, mais donner uniquement des personnes à l'extérieur du fichier C un pointeur. (Oui, je sais qu'ils pourraient potentiellement gâcher avec elle, donc ce n'est pas tout à fait comme le mot clé privé de Java, mais ça va avec moi).

Quoi qu'il en soit, j'utilise le code suivant et j'ai regardé C'est aujourd'hui et je suis vraiment surpris que cela fonctionne réellement, quelqu'un peut-il expliquer pourquoi c'est?

dans mon fichier C, je crée ma structure, mais ne lui donnez pas une étiquette dans l'espace de noms Typedef : xxx

et dans le fichier h, je mets ceci: xxx

J'utilise évidemment #include "Laball. H "dans le fichier C, mais je n'utilise pas #include" Laball.c "dans le fichier d'en-tête, comme cela vaincre tout le but d'un fichier d'en-tête séparé. Alors, pourquoi ai-je capable de créer un pointeur sur la Laball * struct dans le fichier h quand je ne l'ai pas incité? At-il quelque chose à voir avec l'espace de noms d'installation de fichiers accrocs, même lorsqu'un fichier n'est en aucun cas lié à un autre?

merci.


2 commentaires

Cacher le fait que quelque chose est un pointeur est généralement considéré comme un style. Et il n'est pas nécessaire - les pointeurs opaques fonctionnent bien en C, jetez un coup d'œil au fichier * par exemple - il n'y a pas de type de pointeur de fichier spécial.


D'accord, merci. Je suis tout à fait aussi utilisé pour lame Java, quelles coutures à aimer pour cacher le fait que tout est un pointeur.


3 Réponses :


1
votes

dans xxx

puisque toutes les interfaces des pointeurs sont les mêmes, sachant que B signifie qu'un pointeur à une structure A contient déjà suffisamment d'informations. La mise en œuvre réelle d'A est sans importance (cette technique est appelée "pointeur opaque".)

(BTW, mieux renommer l'un des Laball . Il est confus que le même nom est utilisé pour des types incompatibles.)


2 commentaires

Vraiment, j'ai pensé au fait que seul l'un d'entre eux existait dans l'espace de noms des structures, et l'un d'entre eux existait dans l'espace de nom de Typedef serait suffisant pour les distinguer? Oh bien, je vais faire ça, merci.


@Leif: C'est bien pour le compilateur , mais les utilisateurs seront confus, en particulier ceux utilisant C ++.



25
votes

Un modèle standard pour des trucs similaires est d'avoir un fichier foo.h code> définissant l'API comme xxx pré>

et un foo.c Code> Fichier fournissant une implémentation pour cette API comme p>

#include "foo.h"

void broken() {
    Foo f;
    foo_do_something(&f);
}


0 commentaires

7
votes

Puisque vous posez une raison précise de "pourquoi" la langue fonctionne de cette façon, je suppose que vous voulez des références précises. Si vous trouvez que le pédant, sautez simplement les notes ...

Cela fonctionne à cause de deux choses:

  • Tous les types de structure des structures ont la même représentation (note que c'est pas vrai de tous les types de pointeur, en ce qui concerne la norme C. [1] Par conséquent, le compilateur a suffisamment d'informations pour générer un code approprié pour toutes les utilisations de votre type de pointeur à struct.

  • L'espace de noms Tag (Strat, Enum, Union) est en effet compatible avec toutes les unités de traduction. [2] Ainsi, les deux structures (même si on n'est pas complètement définie, c'est-à-dire que cela manque de déclarations membres) en sont un et le même.

    (BTW, #import est non standard.)

    [1] selon N1256 §6.2.5.27:

    Tous les pointeurs aux types de structure doivent avoir les mêmes exigences de représentation et d'alignement les uns des autres. Les pointeurs vers d'autres types n'ont pas besoin de la même représentation ou des mêmes exigences d'alignement.

    [2] selon N1256 §6.2.7.1:

    Deux types de structure, d'union ou d'énuméré déclaré dans des unités de traduction distinctes sont compatibles si leurs balises et leurs membres répondent aux exigences suivantes: Si l'une est déclarée avec une balise, l'autre doit être déclarée avec la même balise. Si les deux sont des types complets, les exigences supplémentaires suivantes s'appliquent: [ne nous concerne pas].


1 commentaires

"(BTW, #import est non standard.)" Woops, je mélangeais Java ... je voulais taper #include. :) Je vais résoudre ça.