12
votes

Comment puis-je cacher la déclaration d'une structure en C?

dans la question Pourquoi devrions-nous typez une structure Si souvent en C? , vous détendez-vous que:

Dans ce dernier cas, vous ne pouvez pas retourner le point de valeur, depuis sa La déclaration est cachée des utilisateurs de le fichier d'en-tête. C'est une technique utilisé largement dans GTK +, par exemple.

Comment la déclaration est-elle accomplie? Pourquoi ne puis-je pas retourner le point par valeur?

Ajouter:

J'ai compris pourquoi je ne peux pas retourner la structure par valeur, mais c'est toujours difficile de voir pourquoi je peux 'T de déférence Ce point dans ma fonction. I.e. Si ma structure a un membre nommé y, pourquoi je ne peux pas le faire? xxx

Pourquoi devrais-je utiliser des méthodes pour le faire? (Comme GTK +)

Merci gars, et désolé pour mon mauvais anglais à nouveau.

c

0 commentaires

6 Réponses :


36
votes

Regardez cet exemple d'une bibliothèque, à l'aide d'un fichier d'en-tête public, d'un fichier d'en-tête privé et d'un fichier de mise en œuvre.

dans le fichier public.h em>: p>

struct Point* getSomePoint()
{
    /* ... */
}


3 commentaires

@ Chux-Restassatemonica vous avez raison, juste fixé cela.


Si je veux déclarer une structure dans file.c à utiliser uniquement dans fichier.c , est-ce possible?


@ Mercury0114 Si vous déclarez une structure intérieure file.c Il ne sera visible que ci-dessous ce point de déclaration intérieure fichier.c .



6
votes

Ce qu'il veut dire, c'est que vous ne pouvez pas retourner la valeur de la structure dans l'en-tête, car pour cela, la structure doit être complètement déclarée. Mais cela se produit dans le fichier C (la déclaration qui rend x un type complet est "cachée" dans le fichier C et non exposé à l'en-tête), dans son exemple. Ce qui suit ne déclare qu'un type incomplet, si c'est la première déclaration de la structure xxx

alors, vous pouvez déclarer la fonction xxx

mais Vous ne pouvez pas définir la fonction, car vous ne pouvez pas créer une variable de ce type, et beaucoup moins encore, ce qui le retourne (sa taille n'est pas connue). xxx

L'erreur se produit car "x" est toujours incomplète. Maintenant, si vous n'incluez que l'en-tête avec la déclaration incomplète, vous ne pouvez pas appeler cette fonction, car l'expression de l'appel de fonction produirait un type incomplet, interdit de se produire.

Si vous deviez fournir une déclaration du type complet struct x entre, il serait valide xxx

ceci s'appliquerait à la manière d'utiliser Typedef aussi: ils nomment tous les deux le même type (éventuellement incomplet). Une fois en utilisant un identifiant ordinaire x , et une autre fois à l'aide d'une balise struct x .


0 commentaires

5
votes

dans le fichier d'en-tête:

struct _point f() {
  ....
}
  • Il y a un struct code> appelé _point code>. li>
  • Il y a un type de pointeur point code> qui peut se référer à un point struct _point code>. li> ul>

    Le compilateur ne sait pas: p>

    • Qu'est-ce que le struct _point code> ressemble à. li>
    • quels éléments struct _point code> contient. li>
    • Quelle est la taille structure _point code> est. li> ul>

      Non seulement le compilateur ne le sait pas - nous, car les programmeurs ne le savent pas non plus. Cela signifie que nous ne pouvons pas écrire un code qui dépend de ces propriétés de struct _point code>, ce qui signifie que notre code peut être plus portable. p>

      Compte tenu du code ci-dessus, vous pouvez écrire des fonctions telles que: p> xxx pré>

      car point code> est un pointeur et struct code> Les pointeurs sont tous de la même taille et le compilateur n'a pas besoin de savoir quoi que ce soit d'autre. Mais vous ne pouvez pas écrire une fonction qui retourne de valeur: p> xxx pré>

      car le compilateur ne sait rien sur structure _point code>, spécifiquement sa taille, dont il a besoin pour construire la valeur de retour. p>

      Ainsi, nous ne pouvons que faire référence à structure _point code> via le type code>, ce qui est vraiment une aiguille. C'est pourquoi Standard C a des types tels que le fichier code>, qui ne peut être accédé que via un pointeur - vous ne pouvez pas créer une instance de structure code> de fichier code> dans votre code. P> p>


0 commentaires

3
votes

Qu'est-ce que ce message post est: Si vous voyez l'en-tête

typedef struct _Point Point;

Point * point_new(int x, int y);


0 commentaires

1
votes

Au fur et à mesure de l'utilisation des pointeurs opaques (comme d'autres personnes ont mentionné), vous pouvez plutôt renvoyer un sac opaque d'octets si vous souhaitez éviter d'utiliser la mémoire de tas: xxx

alors, vous pouvez. Créez des instances de la structure sur la pile dans le code du client, mais le client ne sait pas ce qu'il y a dedans - tout ce qu'il sait, c'est que c'est une blob d'octets avec une taille donnée. Bien sûr, cela peut toujours accéder aux données si elle peut deviner les décalages et les types de données des membres, mais vous avez à nouveau le même problème avec les pointeurs opaques (bien que les clients ne connaissent pas la taille de l'objet dans ce cas).

Par exemple, les différentes structures utilisées dans la bibliothèque Bibliothèque utilisent des structs d'octets opaques pour types tels que pthread_t , pthread_cond_t , etc., . - Vous pouvez toujours créer des instances de ceux de la pile (et vous le faites habituellement), mais vous n'avez aucune idée de ce qui y est. Il suffit de jeter un coup d'œil à votre /usr/include/pthread.h et des différents fichiers qu'il inclut.


1 commentaires

Vous allez avoir une question d'alignement, le point public le point de structure requis d'alignement natif est basé sur le type de données UINT8_T, par exemple. 1 octet, tandis que les exigences d'alignement d'alignement indigènes sont basées sur int , probablement 4 octets. J'ai essayé d'expliquer le problème en réponse Stackoverflow.com/a/17619016/611560 Cordialement.



2
votes

Vieille question, meilleure réponse:

dans le fichier d'en-tête: p> xxx pré>

in c fichier: p>

struct _Point
{
   int X;
   int Y;
};


0 commentaires