J'ai vu beaucoup de questions sur ce sujet mais je vais poser la question différemment sans code spécifique. Existe-t-il un moyen de EASILY déterminer ce qui fait que le type est incomplet ? Dans mon cas, j'utilise le code de quelqu'un d'autre et je suis tout à fait sûr que je n'ai pas les bons en-têtes, mais (puisque les ordinateurs font ce genre de choses beaucoup plus vite et mieux que les yeux humains) y a-t-il un moyen de faire en sorte que le compilateur dise, "hey vous piense en vous avez le type X à la ligne 34 mais c'est en fait manquant ." L'erreur elle-même n'apparaît qu'au moment de l'affectation, ce qui n'est pas très utile.
Réponses
Trop de publicités?A - Solution
En ce qui concerne le langage C, je viens de découvrir amplement que le code de déclaration suivant sera la solution ;
typedef struct ListNode
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Donc, en règle générale, je donne le même nom à la fois pour la définition du type et pour le nom de la structure ;
typedef struct X
{
// code for additional types here
X* prev; // reference to pointer
X* next; // reference to pointer
} X;
B - Échantillons problématiques
Lorsque les déclarations suivantes sont considérées à la fois comme incomplètes par la gcc
compilateur lors de l'exécution de l'instruction suivante ;
removed->next->prev = removed->prev;
Et j'obtiens la même erreur pour le code de déréférencement indiqué 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 fichier d'en-tête les déclarations énumérées ci-dessous ;
typedef struct
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Plus celui-là ;
typedef struct ListNodeType
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
En dehors des scénarios possibles impliquant une optimisation de l'ensemble du 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;
}
ne sera pas du tout affectée par ce que les membres struct foo
peut contenir. Parce que les utilitaires make recompileront généralement toute unité de compilation dans laquelle la définition complète d'une structure apparaît, même lorsque de tels changements ne pourraient pas réellement affecter le code généré pour eux, il est courant d'omettre les définitions de structure complètes des unités de compilation qui n'en ont pas réellement besoin, et une telle omission n'est généralement pas digne d'un avertissement.
Un compilateur doit disposer d'une définition complète de la structure ou de l'union pour savoir comment traiter les déclarations d'objets du type avec durée automatique ou statique, les déclarations d'agrégats contenant des membres du type, ou le code qui accède aux membres de la structure ou de l'union. Si le compilateur ne dispose pas des informations nécessaires pour effectuer l'une des opérations ci-dessus, il n'aura d'autre choix que de s'en plaindre.
Par ailleurs, il existe une autre situation dans laquelle la norme permettrait à un compilateur d'exiger qu'une définition d'union complète soit visible, mais n'exigerait pas de diagnostic : si deux structures commencent par une séquence initiale commune, et qu'un type d'union contenant les deux est visible lorsque le compilateur traite du code qui utilise un pointeur de l'un des types de structure pour inspecter un membre de cette séquence initiale commune, le compilateur est tenu de reconnaître que ce code pourrait accéder au membre correspondant d'une structure de l'autre type. Je ne sais pas quels compilateurs, s'il y en a, se conforment à la norme lorsque le type d'union complet est visible, mais pas lorsqu'il ne l'est pas [gcc a tendance à générer du code non conforme dans les deux cas, à moins que l'option de la séquence initiale commune ne soit activée]. -fno-strict-aliasing
est utilisé, auquel cas il générera du code conforme dans les deux cas] mais si l'on veut écrire du code qui utilise la règle CIS de manière à garantir un comportement correct sur les compilateurs conformes, il faut s'assurer que la définition complète du type d'union est visible ; si ce n'est pas le cas, un compilateur peut générer silencieusement du code erroné.
- Réponses précédentes
- Plus de réponses