[C] Comment éviter les warnings pour "déclaration implicite de"

Comment éviter les warnings pour "déclaration implicite de" [C] - C - Programmation

Marsh Posté le 10-04-2009 à 13:57:40    

Bonjour à tous,  
 
Je suis en train de travailler sur un projet en C et j'ai quelques fois des warnings comme celui-ci :
 
Tokener.c:54: attention : déclaration implicite de la fonction « «isblank» »
 
Je ne comprends pas bien ce qu'il signifie et je ne sais forcément pas les corriger.  
 
Le programme semble pourtant se comporter comme voulu, mais je voudrais que ce code soit propre.
 
Pourriez-vous me renseigner?  
 
D'avance merci...
 
DL

Message cité 1 fois
Message édité par damien_leroy7 le 10-04-2009 à 13:58:15
Reply

Marsh Posté le 10-04-2009 à 13:57:40   

Reply

Marsh Posté le 10-04-2009 à 14:06:38    

Est-ce que la fonction isblank() et ses lignes de code, se trouvent avant ou après l'appel à cette fonction ? Il semble que le code de isblank() se trouve après son appel (auquel cas il faudrait changer de place les lignes de code), ou qu'il se trouve dans un autre fichier, et qu'il manque une déclaration d'un "prototype" pour cette fonction (auquel cas il faudrait rajouter un prototype). Dans les tutoriels, voir le mot clé "prototype" de fonction.

Reply

Marsh Posté le 10-04-2009 à 14:43:13    

#include <ctype.h>
 
ça devrait mieux marcher.
En C il faut mettre les #include correspondants aux fonctions qu'on utilise. En cas de doute, mieux vaut en mettre trop que pas assez.
 
Par contre en C, au sens strict du langage, toute fonction qui retourne un entier peut être utilisée sans déclaration, d'où le fait que tu aies un warning et pas une erreur, mais c'est déconseillé.

Reply

Marsh Posté le 10-04-2009 à 16:44:46    

damien_leroy7 a écrit :


Tokener.c:54: attention : déclaration implicite de la fonction « «isblank» »
 
Je ne comprends pas bien ce qu'il signifie et je ne sais forcément pas les corriger.  


Ca signifie que tu appelles une fonction sans avoir fourni de prototype au préalable. Le compilateur fait alors des hypothèses sur le type des paramètres et le retour. Il ne vérifie pas si le nombre de paramètres est conforme. Le comportement est donc indéterminé.
 
Pour coder correctement, il faut fournir un prototype. c'est le rôle des headers (.h) qui contiennent précisément les prototypes des fonctions.
 

Code :
  1. #include <ctype.h>



---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 10-04-2009 à 16:55:35    

Emmanuel Delahaye a écrit :


Ca signifie que tu appelles une fonction sans avoir fourni de prototype au préalable. Le compilateur fait alors des hypothèses sur le type des paramètres et le retour. Il ne vérifie pas si le nombre de paramètres est conforme. Le comportement est donc indéterminé.
 
Pour coder correctement, il faut fournir un prototype. c'est le rôle des headers (.h) qui contiennent précisément les prototypes des fonctions.
 

Code :
  1. #include <ctype.h>




 
Le compilateur fait exactement une et une seule hypothèse : que le type de retour est entier.
Le comportement est determiné : la valeur de retour sera castée bit-à-bit depuis un entier. Les paramètres sont toujours bien passés, de toute façon en C on peut passer n'importe quoi en paramètre.

Reply

Marsh Posté le 10-04-2009 à 17:07:34    

jesus_christ a écrit :


 
Le compilateur fait exactement une et une seule hypothèse : que le type de retour est entier.
Le comportement est determiné : la valeur de retour sera castée bit-à-bit depuis un entier. Les paramètres sont toujours bien passés, de toute façon en C on peut passer n'importe quoi en paramètre.


Et la marmotte ...

Code :
  1. #include <stdio.h>
  2. int main (void)
  3. {
  4.    print (123);
  5.    return 0;
  6. }
  7. void print (double x)
  8. {
  9.    printf ("%f\n", x);
  10. }



0.000000
 
Process returned 0 (0x0)   execution time : 0.084 s
Press any key to continue.


alors que

Code :
  1. #include <stdio.h>
  2. void print (double x);
  3. int main (void)
  4. {
  5.    print (123);
  6.    return 0;
  7. }
  8. void print (double x)
  9. {
  10.    printf ("%f\n", x);
  11. }



123.000000
 
Process returned 0 (0x0)   execution time : 0.023 s
Press any key to continue.


Message édité par Emmanuel Delahaye le 10-04-2009 à 17:08:50

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-04-2009 à 10:31:57    

Merci à tous pour ces informations utiles. En fait, je ne savais pas que isblank faisait partie de ctype.h
 
Encore un grand merci :)

Reply

Marsh Posté le 11-04-2009 à 11:41:16    

L'exemple qui calme tout de suite...
 
Ceci dit, sur Visual Studio 2009, le premier ex. ne compile pas:
warning C4013: 'print' non défini(e) ; extern retournant int pris par défaut
error C2371: 'print' : redéfinition ; types de base différents

Message cité 2 fois
Message édité par el muchacho le 11-04-2009 à 11:52:12

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 11-04-2009 à 12:39:52    

el muchacho a écrit :

L'exemple qui calme tout de suite...
 
Ceci dit, sur Visual Studio 2009, le premier ex. ne compile pas:
warning C4013: 'print' non défini(e) ; extern retournant int pris par défaut
error C2371: 'print' : redéfinition ; types de base différents


 
Comme je l'avais dit, le compilateur suppose que c'est une fonction prenant des arguments arbitraires et retournant un entier. Par contre les casts d'arguments nécessaires ne sont pas faits, faute de connaître le bon type, un peu comme pour les arguments de printf, c'est le point qu'a révélé E.D.
 
Si VC2009 ne compile pas c'est parce qu'il applique certaines règles du C++ au C, le code de E.D. est tout a fait correct en C89.
De toute manière, il faut mettre les bons includes pour toutes les fonctions qu'on utilise.
Pour une ref sur les correspondances fonction/entête du C, voir :
http://www.ime.usp.br/~marioct/mac5710/ansic.html

Reply

Marsh Posté le 11-04-2009 à 12:59:46    

el muchacho a écrit :

L'exemple qui calme tout de suite...
 
Ceci dit, sur Visual Studio 2009, le premier ex. ne compile pas:
warning C4013: 'print' non défini(e) ; extern retournant int pris par défaut
error C2371: 'print' : redéfinition ; types de base différents


Il ne compile pas en C++. Mais il compile en C. Attention à utiliser le bon compilateur. Pour être sûr : ajouter ceci au code source :  

Code :
  1. #ifdef __cplusplus
  2. #error Be sure you are using a C compiler...
  3. #endif



---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-04-2009 à 12:59:46   

Reply

Marsh Posté le 11-04-2009 à 13:23:51    

jesus_christ a écrit :

Par contre en C, au sens strict du langage, toute fonction qui retourne un entier peut être utilisée sans déclaration,

 

En C90 et sous réserve qu'il n'y ait pas d'arguments variadiques ni d'un type qui serait promu quand on le passe à une fonction dont on n'a pas le prototype (char, short, float) et qu'on passe bien des arguments du bon type après promotion (Emmanuel a donné l'exemple d'une conversion int->double, il y a aussi NULL qu'il faut caster alors dans le bon type et, si on veut être strict, les implémentations où ça pose un problème étant rarissimes, les pointeurs à caster en void* si besoin est; c'est exactement les mêmes cas auxquels il faut faire attention dans les arguments variadiques).

 

En C99 les déclarations implicites de fonctions ne sont pas autorisées (gcc a besoin de -pedantic-error pour en faire une erreur en C99).

Message cité 3 fois
Message édité par Un Programmeur le 11-04-2009 à 13:26:09
Reply

Marsh Posté le 11-04-2009 à 14:21:07    

Un Programmeur a écrit :

En C99 les déclarations implicites de fonctions ne sont pas autorisées (gcc a besoin de -pedantic-error pour en faire une erreur en C99).


Si, c'est autorisé (bien que fortement déconseillé, comme il a été démontré) . Ce qui ne l'est pas c'est le type retour implicite.
 
OK en C90, ne compile pas en C99 :  

Code :
  1. f()
  2. {
  3. }


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-04-2009 à 16:32:38    

Un Programmeur a écrit :


 
En C90 et sous réserve qu'il n'y ait pas d'arguments variadiques ni d'un type qui serait promu quand on le passe à une fonction dont on n'a pas le prototype (char, short, float) et qu'on passe bien des arguments du bon type après promotion (Emmanuel a donné l'exemple d'une conversion int->double, il y a aussi NULL qu'il faut caster alors dans le bon type et, si on veut être strict, les implémentations où ça pose un problème étant rarissimes, les pointeurs à caster en void* si besoin est; c'est exactement les mêmes cas auxquels il faut faire attention dans les arguments variadiques).
 
En C99 les déclarations implicites de fonctions ne sont pas autorisées (gcc a besoin de -pedantic-error pour en faire une erreur en C99).


 

Emmanuel Delahaye a écrit :


Si, c'est autorisé (bien que fortement déconseillé, comme il a été démontré) . Ce qui ne l'est pas c'est le type retour implicite.
 
OK en C90, ne compile pas en C99 :  

Code :
  1. f()
  2. {
  3. }



 
Tu as une référence?
 
J'ai les deux normes sous les yeux et le second alinéa de la section "Semantics" de 6.3.2.2 "Function calls" de C90:
 

Citation :

If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration
 
extern int identifier ();
 
appeared.


 
n'a pas d'équivalent dans 6.5.2.2.  Et je ne trouve nulle part ailleurs quelque chose d'équivalent.  Ca a pu m'échapper, mais jusqu'à preuve du contraire, je considère que ce n'est plus autorisé.   gcc donnant une erreur avec -std=c99 -pedantic-error, j'ai l'impression que ses auteurs ont la même interprétation.

Reply

Marsh Posté le 11-04-2009 à 16:50:28    

Emmanuel Delahaye a écrit :


Il ne compile pas en C++. Mais il compile en C. Attention à utiliser le bon compilateur. Pour être sûr : ajouter ceci au code source :  

Code :
  1. #ifdef __cplusplus
  2. #error Be sure you are using a C compiler...
  3. #endif




OK. Effectivement, sous Visual Studio, j'ai pas trop cherché comment forcer le compiler à C. En tout cas, je vais certainement envoyer ton exemple à certains collègues qui ne prennent pas la peine de déclarer toutes leurs fonctions. :jap:


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 11-04-2009 à 17:03:13    

Un Programmeur a écrit :

[...]En C99 les déclarations implicites de fonctions ne sont pas autorisées [...]


Je dirais aussi que c'est toi qui a raison là.
Sun aussi a la même interprétation.
http://docs.sun.com/source/819-3688/c99.app.html#54208

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed