Question

J'ai vu beaucoup de questions sur cela, mais je vais demander à la question autrement sans code spécifique. Est-il possible de FACILEMENT déterminer ce qui est à l'origine du genre à être incomplète? Dans mon cas, je suis en utilisant le code de elses quelqu'un et je suis tout à fait sûr que je n'ai pas les en-têtes à droite, mais (car les ordinateurs font ce genre de choses beaucoup plus vite et mieux que les globes oculaires humains) est-il un moyen d'obtenir le compilateur de dire , "hey you que vous avez le type X à la ligne 34, mais qui est en fait manquant ." L'erreur ne se montre que lorsque vous attribuez, ce qui est très utile.

Était-ce utile?

La solution

J'ai vu une question l'autre jour où quelqu'un par mégarde utilisé un type incomplet en spécifiant quelque chose comme

struct a {
    int q; 
}; 
struct A *x; 
x->q = 3;

Le compilateur savait que struct A était un struct, en dépit A étant totalement indéfini, en vertu du mot-clé struct.

C'était en C ++, où une telle utilisation de struct est atypique (et, il se trouve, peut conduire à pied tir). En C, si vous faites

typedef struct a {
    ...
} a;

vous pouvez alors utiliser a comme typename et omettre le struct plus tard. Cela conduira le compilateur pour vous donner une erreur d'identification non défini plus tard, plutôt que de type incomplet, si vous le nom ou une faute de frappe oublier un en-tête.

Autres conseils

Une autre raison possible est une référence indirecte. Si une des références de code à une struct qui ne figurent pas dans le fichier actuel c, le compilateur se plaindra.

  

a-> b-> c // erreur si b non inclus dans le fichier actuel c

Que voulez-vous dire, l'erreur ne montre que lorsque vous attribuez? Par exemple sur GCC, sans affectation en vue:

int main() {
    struct blah *b = 0;
    *b; // this is line 6
}

incompletetype.c:6: error: dereferencing pointer to incomplete type.

L'erreur à la ligne 6, qui est où je un type incomplet comme si elle était un type complet. J'étais bien jusque-là.

L'erreur est que vous devez avoir inclus tout en-tête définit le type. Mais le compilateur ne peut peut-être deviner quelle ligne qui aurait dû être inclus à: tout en dehors de la ligne d'une fonction serait bien, à peu près. Ni est ce que ça va aller la pêche au chalut dans chaque fichier texte sur votre système, la recherche d'un en-tête qui le définit, et vous suggère de l'inclure.

Sinon (bon point, potatoswatter), l'erreur est à la ligne où b a été définie, lorsque vous voulais dire pour spécifier un type qui existe effectivement, mais blah effectivement spécifié. Trouver la définition de la b variable ne devrait pas être trop difficile dans la plupart des cas. IDEs peut habituellement le faire pour vous, les avertissements du compilateur ne peuvent pas être pris la peine peut-être. Il est un code assez odieux, cependant, si vous ne trouvez pas les définitions des choses que vous utilisez.

Je ne comprends pas exactement quel est le problème. type incomplet n'est pas le type qui est « manquant ». le type Incompete est un type qui est a déclaré mais pas défini (dans le cas des types de struct). Pour trouver la déclaration de non-définition est facile. Quant à la définition de trouver la manquante ... le compilateur ne vous aidera pas ici, puisque c'est ce qui a causé l'erreur en premier lieu.

Une raison majeure pour les erreurs de type incomplet dans C sont des fautes de frappe dans les noms de type, ce qui empêche le compilateur de correspondre un nom à l'autre (comme dans la déclaration correspondant à la définition). Mais encore une fois, le compilateur ne peut pas vous aider. Compilateur ne fait pas des suppositions sur les fautes de frappe.

cette erreur généralement indique si le nom de votre struct est différent de l'initialisation de votre struct dans le code, donc normalement, c trouvera le nom du struct que vous mettez et si le struct d'origine ne se trouve pas, cela habituellement apparaissent, ou si vous pointez un pointeur dans ce pointeur fait, l'erreur sera affiché.

A - Solution

En parlant de la langue C, je viens de trouver ampirically qui suit le code de déclaration sera la solution;

typedef struct ListNode
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

En règle générale, je donne le même nom à la fois pour les deux définition de type et le nom du struct;

typedef struct X
{
    // code for additional types here
    X* prev; // reference to pointer
    X* next; // reference to pointer
} X;

B - Les échantillons Problemetic

Lorsque des déclarations suivantes sont considérées à la fois incomplète par le compilateur gcc lors de l'exécution déclaration suivante. ;

removed->next->prev = removed->prev;

Et je reçois même erreur pour le code de déréférencement rapporté dans la sortie d'erreur;

>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
     removed->next->prev = removed->prev;

Pour les deux déclarations ci-dessous fichier d'en-tête

typedef struct
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

De plus celui-ci;

typedef struct ListNodeType
{
    int data;
    ListNode * prev;
    ListNode * next;
} ListNode;

En dehors des scénarios possibles concernant l'optimisation tout le programme, le code généré pour quelque chose comme:

struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
  return blah ? whatever: bar;
}

sera totalement affecté par ce que les membres struct foo peut contenir. Parce que les services publics make ne recompiler généralement une unité de compilation dans laquelle la définition complète d'une structure apparaît, même si ces changements ne pourrait effectivement affecter le code généré pour eux, il est courant d'omettre les définitions de structure complète des unités de compilation qui ne sont pas réellement besoin eux, et cette omission est généralement pas digne d'un avertissement.

A besoin du compilateur d'avoir une définition complète de la structure ou d'une union de savoir comment gérer les déclarations des objets du type à durée automatique ou statique, les déclarations d'agrégats contenant des membres du type ou du code qui accède à des membres de la structure ou d'une union. Si le compilateur ne dispose pas des informations nécessaires pour effectuer l'une des opérations ci-dessus, il n'aura pas d'autre choix que de couac à ce sujet.

Soit dit en passant, il y a une situation plus où la norme permettrait un compilateur d'exiger une définition de l'union complète pour être visible mais ne nécessiterait pas de diagnostic: si deux structures commencent par une séquence initiale commune, et un type d'union contenant à la fois visible lorsque le compilateur est le code de traitement qui utilise un pointeur de l'un des types de structure à inspecte un membre de cette séquence initiale commune, le compilateur est nécessaire de reconnaître que ce code pourrait être d'accéder au membre correspondant d'une structure de l'autre type. Je ne sais pas ce que compilateurs le cas échéant conformes à la norme lorsque le type d'union complète est visible, mais pas quand il est pas [gcc est sujette à générer du code non conforme dans les deux cas à moins que le drapeau -fno-strict-aliasing est utilisé, auquel cas il va générer un code conforme dans les deux cas], mais si l'on veut écrire du code qui utilise la règle de la CEI de telle façon à garantir un comportement correct sur compilateurs conforme, il peut être nécessaire de faire en sorte que la définition type union complète est visible; omission de le faire peut entraîner un compilateur générant un code factice en mode silencieux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top