Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2464 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Contrôle de type sur les macros

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Contrôle de type sur les macros

n°1532512
lafourchet​te
Posté le 23-03-2007 à 09:35:36  profilanswer
 

Bonjour
 
Je peux lire dans beaucoup de documentations que les macros sont dangereuses parce qu'il n'y a aucun contrôle de type effectué dessus. Je ne comprends pas pourquoi  :??:  
Si j'ai bien lu le principe des macros, c'est du simple remplacement de texte effectué par le préprocesseur avant compilation. Si je remplace moi même à la main mes appels de macro par le code correspondant, le compilateur effectuera bien un contrôle sur les types ?
Où est la différence? :heink:  
Où fais je l'erreur?

Message cité 1 fois
Message édité par lafourchette le 23-03-2007 à 09:41:11
mood
Publicité
Posté le 23-03-2007 à 09:35:36  profilanswer
 

n°1532782
Emmanuel D​elahaye
C is a sharp tool
Posté le 23-03-2007 à 14:01:34  profilanswer
 

lafourchette a écrit :

Je peux lire dans beaucoup de documentations que les macros sont dangereuses parce qu'il n'y a aucun contrôle de type effectué dessus. Je ne comprends pas pourquoi  :??:  
Si j'ai bien lu le principe des macros, c'est du simple remplacement de texte effectué par le préprocesseur avant compilation. Si je remplace moi même à la main mes appels de macro par le code correspondant, le compilateur effectuera bien un contrôle sur les types ?
Où est la différence? :heink:  
Où fais je l'erreur?


Ca pose problème dans les pseudo fonctions avec paramètres. Les paramètres des macros ne sont pas typés et font simplement un remplacement de texte.

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. /* 0|1 */
  4. #if 1
  5. #define str_to_double(s, p)\
  6.    *p = strtod(s, NULL)
  7. #else
  8. void str_to_double(char const *s, double *p)
  9. {
  10.    *p = strtod(s, NULL);
  11. }
  12. #endif
  13. int main (void)
  14. {
  15.    int x;
  16.    char line[] = "1234.56";
  17.    str_to_double (line, &x);
  18.    printf ("%d\n", x);
  19.    return 0;
  20. }


Avec la macro : pas de warning
Avec la fonction : warning


---------------
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/
n°1533140
lafourchet​te
Posté le 24-03-2007 à 13:15:02  profilanswer
 

Ainsi présenté, c'est déjà plus lumineux.  :jap:  
 
Dans le cas 0, le cas de la fonction, j'ai effectivement un warning:
 [Warning] passing arg 2 of `str_to_double' from incompatible pointer type  
Le compilateur à, je suppose, constaté  qu'à l'appel de la fonction "str_to_double", les paramètres effectifs divergeaient par rapport aux paramètres formels.
Mais je peux executer le programme et j'obtiens:
1889785610 Résultat sans doute sans signification intinsèque mais qui doit pouvoir s'expliquer.  
 
Dans le cas 1, le cas de la macro, tout se passe bien et j'obtiens:
1234 Résultat que cette fois ci je peux expliquer.  :D  
 
Par contre, dans les deux cas j'ai commis à la lecture du code, une erreur  de débutant et j'espère que je suis pas le seul:  :(  
J'étais persuadé que le compilateur m'enverrait un petit avertissement de principe pour essayer d'affecter le contenu d'une variable de type double à une variable de type int.

n°1533230
Sve@r
Posté le 24-03-2007 à 19:16:02  profilanswer
 

lafourchette a écrit :

J'étais persuadé que le compilateur m'enverrait un petit avertissement de principe pour essayer d'affecter le contenu d'une variable de type double à une variable de type int.


Où vois-tu une affectation de double vers int ? strtod() renvoie un double, "p" étant de type "double étoile" il s'ensuit que "*p" est de type "double" donc en affectant "strtod()" à "*p" tout est correct...
 

lafourchette a écrit :

Mais je peux executer le programme et j'obtiens:
1889785610 Résultat sans doute sans signification intinsèque mais qui doit pouvoir s'expliquer.


De façon très facile: la fonction "strtod" à laquelle tu passes un pointeur (une adresse) ira stocker à cette adresse les 8 octets correspondant à une valeur au format "double" qu'elle calcule, valeur codée sur 8 octets (selon les spécifications du codage des double avec la mantisse, l'exposant, etc...).
 
Toi, tu lui passes l'adresse d'un "int" qui est convertie en adresse de double par le cast implicite. Une adresse étant toujours une adresse et étant considérée comme pointant sur 8 octets au format "double", la fonction va donc stocker à cette adresse les 8 octets du double (ici risque de plantage car il est possible que les 4 octets suivants le "int" ne soient pas disponibles mais passons).
Au retour de la fonction, quand tu affiches ton "int", ça récupère les 4 premiers octets de la zone mémoire correspondante, les décode selon les spécifications du codage des "int" (1 bit de signe, 31 bits de valeur) et t'affiche le résultat.
Donc t'as codé en spécification "double" et tu décodes en spécifications "int". Déjà que les spécifications ne sont pas les mêmes et en plus tu n'en décodes que la moitié de ce qui a été mis. C'aurait été miraculeux que tu obtiennes "1234"...

Message cité 1 fois
Message édité par Sve@r le 24-03-2007 à 19:40:00

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1533789
lafourchet​te
Posté le 26-03-2007 à 15:37:41  profilanswer
 

Sve@r a écrit :


 
De façon très facile: la fonction "strtod" à laquelle tu passes un pointeur (une adresse) ira stocker à cette adresse les 8 octets correspondant à une valeur au format "double" qu'elle calcule, valeur codée sur 8 octets (selon les spécifications du codage des double avec la mantisse, l'exposant, etc...).
 
Toi, tu lui passes l'adresse d'un "int" qui est convertie en adresse de double par le cast implicite. Une adresse étant toujours une adresse et étant considérée comme pointant sur 8 octets au format "double", la fonction va donc stocker à cette adresse les 8 octets du double (ici risque de plantage car il est possible que les 4 octets suivants le "int" ne soient pas disponibles mais passons).
Au retour de la fonction, quand tu affiches ton "int", ça récupère les 4 premiers octets de la zone mémoire correspondante, les décode selon les spécifications du codage des "int" (1 bit de signe, 31 bits de valeur) et t'affiche le résultat.
Donc t'as codé en spécification "double" et tu décodes en spécifications "int". Déjà que les spécifications ne sont pas les mêmes et en plus tu n'en décodes que la moitié de ce qui a été mis. C'aurait été miraculeux que tu obtiennes "1234"...


 :jap:  

Citation :

Où vois-tu une affectation de double vers int ? strtod() renvoie un double, "p" étant de type "double étoile" il s'ensuit que "*p" est de type "double" donc en affectant "strtod()" à "*p" tout est correct...  


C'est dans le cas de la macro en fait que j'ai un probleme.
Si je fais l'expansion de la macro à son appel j'obtiens
*(&x) = strtod("1234.56", NULL); soit
x = strtod("1234.56", NULL); x étant bien une variable de type int, non  :??:  
Sur deux compilateurs différents, j'ai essayé d'affecter une constante décimale à un int.
Seul le second m'a mis un petit warning  :??:  
 

n°1533912
Sve@r
Posté le 26-03-2007 à 21:08:42  profilanswer
 

lafourchette a écrit :


x = strtod("1234.56", NULL); x étant bien une variable de type int, non  :??:  
Sur deux compilateurs différents, j'ai essayé d'affecter une constante décimale à un int.
Seul le second m'a mis un petit warning  :??:


 
Mouais. Tu peux essayer d'écrire "int x=2.5" voir si ton compilo te mettra un warning. En général, cela tombe dans le cadre du cast implicite...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1534180
matafan
Posté le 27-03-2007 à 12:56:50  profilanswer
 

Tu peux contrôler les types en faisant des affectations dans ta macro :

Code :
  1. #define MA_MACRO(A, B, B) do { \
  2.         int a = A; \
  3.         long b = B; \
  4.         char *c = C; \
  5.         ...
  6. } while (0)

n°1534265
Sve@r
Posté le 27-03-2007 à 14:43:01  profilanswer
 

matafan a écrit :

Tu peux contrôler les types en faisant des affectations dans ta macro :

Code :
  1. #define MA_MACRO(A, B, C) do { \
  2.         int a = A; \
  3.         long b = B; \
  4.         char *c = C; \
  5.         ...
  6. } while (0)



Pourquoi faire une boucle qui ne bouclera pas ???

Code :
  1. #define MA_MACRO(A, B, C) { \
  2.         int a = A; \
  3.         long b = B; \
  4.         char *c = C; \
  5.         ... \
  6. }



---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1534267
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-03-2007 à 14:44:55  profilanswer
 

Sve@r a écrit :

Pourquoi faire une boucle qui ne bouclera pas ???

Code :
  1. #define MA_MACRO(A, B, C) { \
  2.         int a = A; \
  3.         long b = B; \
  4.         char *c = C; \
  5.         ... \
  6. }



Pour forcer l'usage du ';' en fin de macro. C'est une vielle ficelle de métier, je suis étonné que tu ne la connaisses pas...
 


---------------
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/
n°1534275
Sve@r
Posté le 27-03-2007 à 14:50:21  profilanswer
 

Emmanuel Delahaye a écrit :

Pour forcer l'usage du ';' en fin de macro. C'est une vielle ficelle de métier, je suis étonné que tu ne la connaisses pas...


Joli. En plus, je m'étais même dit "tiens il a oublié le ';' après son while mais je ne vais pas lui faire remarquer un truc qui n'est qu'une étourderie" alors que je m'aperçois que c'était voulu ! Bien vu  :bounce:  
 

Emmanuel Delahaye a écrit :

C'est une vielle ficelle de métier, je suis étonné que tu ne la connaisses pas...


Héhé... on ne peut pas tout connaître...  :sol:  


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
mood
Publicité
Posté le 27-03-2007 à 14:50:21  profilanswer
 

n°1534277
0x90
Posté le 27-03-2007 à 14:52:29  profilanswer
 

matafan a écrit :

Tu peux contrôler les types en faisant des affectations dans ta macro :

Code :
  1. #define MA_MACRO(A, B, B) do { \
  2.         int a = A; \
  3.         long b = B; \
  4.         char *c = C; \
  5.         ...
  6. } while (0)



 
Quand on en est à créer un bloc avec son scope, et des variables pour définir le type, on s'approche quand même vachement d'une fonction, il reste quoi comme raison pour ne pas en utiliser une directement ?


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
n°1534317
Emmanuel D​elahaye
C is a sharp tool
Posté le 27-03-2007 à 15:21:53  profilanswer
 

0x90 a écrit :

Quand on en est à créer un bloc avec son scope, et des variables pour définir le type, on s'approche quand même vachement d'une fonction, il reste quoi comme raison pour ne pas en utiliser une directement ?


Next step : inline !
 


---------------
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/
n°1534525
matafan
Posté le 27-03-2007 à 18:05:48  profilanswer
 

Le "do { } while (0)", c'est surtout pour permettre d'utiliser la macro dans un if/else sans bloc, comme on le ferait avec une fonction. Sans le do/while ça donnerait après expansion :

Code :
  1. if (...)
  2.         { ... }; /* Le point virgule est en fait une instruction vide */
  3. else ...


Ce qui ne compile pas puisqu'on a un else sans if. Avec le do/while, ça donne :

Code :
  1. if (...)
  2.         do { ... } while (0); /* Le point virgule fini la mono-instruction du if */
  3. else ...


Et ça c'est bon.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Contrôle de type sur les macros

 

Sujets relatifs
recuperer toutes les valeurs d'un meme type de noeudControle utilisateur autonome
trier le contenu de mon répertoire en fonction du type de fichierObtenir type Class à partir d'un String
function non exécutée après contrôle de formulaireaccess changer format controle
>>>survol d'un texte avec la souris<<<Problème type "fatal error :Cannot instantiate..."
type de requeteTraitement PHP pour balises type BBCODE
Plus de sujets relatifs à : Contrôle de type sur les macros


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR