question bete de #define

question bete de #define - C - Programmation

Marsh Posté le 07-05-2008 à 13:59:10    

heu voili :
quand je fait  :

Code :
  1. #define TOTO (3+4+5)


 
je suppose que TOTO est simplement remplacer par l'expression ? et non executé par la macro pour remplace TOTO par 12 ?
 
Donc comment peut faire en C pour calculer des bouts comme ci-dessus en precompilation ? (si c'est possible)
 
 
 
Newb inside comme vous l'aurez remarqué ;)

Reply

Marsh Posté le 07-05-2008 à 13:59:10   

Reply

Marsh Posté le 07-05-2008 à 14:03:30    

Si je me trompe pas le compilateur remplacera 3+4+5 par 12 lors d'une de ses phases d'optimisation.

Reply

Marsh Posté le 07-05-2008 à 14:03:54    

Ta première analyse est bonne, l'expression "3+4+5" sera remplacée telle quelle dans le code.
 
Pour le calcul, si c'est déterminable avant la compilation (comme dans ton exemple), alors le compilateur le fera durant les phases d'optimisation. Plus bêtement, si le calcul est coûteux, tu peux définir directement le résultat avec un commentaire expliquant d'où sort ce nombre.

Reply

Marsh Posté le 07-05-2008 à 14:12:47    

compile comme ça "gcc -E toto.c"
 
ça te craches le rendu du préprocesseur

Reply

Marsh Posté le 07-05-2008 à 14:20:50    

je suis sous mplab :D (pas top) avec C18 comme compilo

 

merci pour les reponses :jap:

 

l'origine (que j'ai oublié de préciser) :
en fait je suis en phase de test et j'ai fait de petits reglages de timing (changement de quartz, prescaler etc...).
Le truc c'est que ce timing influe partout dans le code et j'en ai raz le bol de tout recalculer pour avoir toujours 1ms (ma reference actuelle)

 

Alors j'ai mis le calcul dans un

Code :
  1. #define 1ms le_calcul


pour les autres endrois

Code :
  1. a = 3*1ms

ou

Code :
  1. #define tempo_min 3*1ms
 

mais dans mon calcul il y a une puissance de 2... du coup le code ne tourne plus (calcul tres long) ; apres une reflexion de 1/4 de seconde j'ai remplacé la puissance de 2 par un decallage :D

Code :
  1. << puissance

et c'était bien plus rapide, mais ca prend tout de meme du temps :/ (le calcul globale) d'où la question.

 

Sinon les calcul sont toujours déterministe et remplacable en direct, mais ca me soule de me farcire les 50 rechercher/remplacer :(


Message édité par $@m le 07-05-2008 à 14:21:23
Reply

Marsh Posté le 07-05-2008 à 14:59:31    

évite les macros. c'est chiant parce que ça se passe pas au niveau du C: pas de typage. Si ton compilateur a ça, crée des constantes avec const

Reply

Marsh Posté le 07-05-2008 à 15:28:20    

ben oui mais là... pas possible de mettre la formule :/

 

j'ai hésité pour les autres constantes (notamment pour le passage par adresse) mais en meme temps je suis tres limité en ram... donc moins de variable declarée const, moins de conso ^^ (c'est vrai ca d'ailleurs ?)


Message édité par $@m le 07-05-2008 à 15:31:13
Reply

Marsh Posté le 07-05-2008 à 15:33:10    

bah ça dépend la taille de ta constante, mais les quelques instructions pour charger la constantes ça peut facilement etre plus léger que plusieurs définitions locales.

Reply

Marsh Posté le 07-05-2008 à 17:13:52    

ah :/

Reply

Marsh Posté le 07-05-2008 à 17:41:44    

bon effectivement c'est assez chiant de ne pas avoir le type du #define...
 
il semble que le calcul sur 4oct ne fonction pas en define :

Code :
  1. #define TEMPS_HORLOGE 102.4
  2. #define TEMPS_BESOIN1 3456000000/((unsigned short)TEMPS_HORLOGE)
  3. // ou #define TEMPS_BESOIN1 3456000000/TEMPS_HORLOGE (au choix) ca fait pareil
  4. unsigned long toto=TEMPS_BESOIN1;


ne fonctionne pas (mauvais resultat)
alors que :

Code :
  1. #define TEMPS_HORLOGE 102.4
  2. unsigned long toto=3456000000/TEMPS_HORLOGE;


fonctionne :/

Reply

Marsh Posté le 07-05-2008 à 17:41:44   

Reply

Marsh Posté le 07-05-2008 à 17:48:24    

Uh ?!
 

Code :
  1. #include <stdio.h>
  2.  
  3. #define TEMPS_HORLOGE 102.4
  4. #define TEMPS_BESOIN1 3456000000/TEMPS_HORLOGE
  5.  
  6. int main(void)
  7. {
  8.   unsigned long taiste_macro=TEMPS_BESOIN1;
  9.   unsigned long taiste = 3456000000/TEMPS_HORLOGE;
  10.  
  11.   printf("Macro : %ld\nSans macro : %ld\n", taiste_macro, taiste);
  12.  
  13.   return 0;
  14. }


 

$ a.out
Macro : 33750000
Sans macro : 33750000

Reply

Marsh Posté le 07-05-2008 à 17:49:21    

Est que t'as déjà entendu parlé du concept de promotion d'entier en C ? Parce que là, j'ai l'impression que tu colles des bouts de code pour que ça tombe en marche....
 
En l'occurence, ça :

Code :
  1. #define TEMPS_BESOIN1 3456000000/((unsigned short)TEMPS_HORLOGE)


Ça calcule la division entière entre l'entier 64bits 3456000000 et l'entier 102. Alors que ça :

Code :
  1. unsigned long toto=3456000000/TEMPS_HORLOGE;


Ça calcule la division réelle entre le réel 3456000000 et le nombre 102.4 (edit: le résultat sera ensuite converti en entier).
 
Normal que tu obtiennes 2 résultats différents, le préprocesseur n'y est stritement pour rien.


Message édité par tpierron le 07-05-2008 à 17:51:52
Reply

Marsh Posté le 07-05-2008 à 17:51:03    

Ouais j'ai répondu pareil et effacé mon post juste après, à cause de :

// ou #define TEMPS_BESOIN1 3456000000/TEMPS_HORLOGE (au choix) ca fait pareil

Reply

Marsh Posté le 07-05-2008 à 18:00:43    

bon... chez moi ca ne donne pas le resultat de Elmoricq

 

mais en fait le 102.4 vient d'un calcul lui meme en maccro...

 

j'ai fait plusieurs essai sur ce calcul, il semble qu'il ne peut y avoir que 1 chiffre apres la virgule.... donc j'ai fait *10 et effectivement tout rentre d'ans l'ordre.
donc effectivement un blem d'entier... cela dit lors des essai j'ai remarqué que l'arrondi parfois differrait (ce qui ne me derangeait pas trop) du à la perte du 0.4 ; mais parfois le resultat etait incompréhensible, comme un débordement ou je ne sais quoi... :??: d'ou le rajout de unsigned short ;)

 

Bref c'est tou bon maintennat merci :jap:

 


PS : la seulle promo dont j'ai entendu parler est celle de canap :D


Message édité par $@m le 07-05-2008 à 18:01:32
Reply

Marsh Posté le 07-05-2008 à 18:01:50    

En ce cas, lis le post de tpierron, c'est exactement ton problème.

Reply

Marsh Posté le 07-05-2008 à 19:08:28    

avec ou sens unsigned c'est pareil, C18 le fait de manière transparente ; mais il calcul aussi avec une taille étrange qui provoque (suivant l'ordre du calcul) des resultats tres étranges...

 

donc oui tpierron à raison, mais si c'était le probleme je m'enserrais vite accomodé ;)

 

maintenant j'ai la précision que je souhaite pour faire 1min @10-3 1s @10-2 juste la 1ms à 8% :/ ais bon c'est normale...

 

maintenant le blem, c'est de faire les divisions en rapide :D
edit : division autre que 2 evidement ;)


Message édité par $@m le 07-05-2008 à 19:08:51
Reply

Marsh Posté le 07-05-2008 à 20:49:31    

C'est pas unsigned le problème qu'évoque tpierron, mais le fait que tu utilises des nombres décimaux dans des calculs d'entiers => promotion en entier => calcul faux.
 
Quand tu cast "102.4" dans un unsigned short, ce type étant entier, tu obtiens "102".
Et donc en faisant "3456000000 / (unsigned short)102.4" => tu calcules en fait "3456000000 / 102".

Reply

Marsh Posté le 08-05-2008 à 00:18:46    

j'avais bine compris... le truc c'est que ... meme en prenant 102, le resultat ne collais pas :/ il y avait comme un debrdement ou un passage en signé ... bref une valeur completement abérente...
 
en meme temps C18.... c'est pas une bete de compete de compilo (gratos fournit par microchip), je ne suis pas à la premiere bizarrerie du genre... le #elif ne fonctionne pas non plus
et les include de fichier qui ne finissent pas par une ligne vide non plus :lol: (tres dure à trouver celle là !! )

Reply

Marsh Posté le 08-05-2008 à 12:11:23    

Toujours terminer ses fichiers par une ligne vide. [:cosmoschtroumpf]

 

J'crois c'est même normé d'ailleurs. [:klemton]

Message cité 1 fois
Message édité par Elmoricq le 08-05-2008 à 12:11:38
Reply

Marsh Posté le 08-05-2008 à 15:37:35    

Elmoricq a écrit :

Toujours terminer ses fichiers par une ligne vide. [:cosmoschtroumpf]
 
J'crois c'est même normé d'ailleurs. [:klemton]


Je suis curieux de savoir pour quelle raison technique cela a été décidé  :??:

Reply

Marsh Posté le 08-05-2008 à 16:02:51    

ca date du glorieux temps antique je pense. C'est comme le coup des 80 colonnes de FORTRAN, une relique.

Reply

Marsh Posté le 08-05-2008 à 21:18:10    

Citation :

Si je me trompe pas le compilateur remplacera 3+4+5 par 12 lors d'une de ses phases d'optimisation.


 :non: Lors de la phase de compilation. Evaluer les constantes littérale n'est pas une optimisation, c'est une obligation pour le compilateur.
 
Sinon on ne pourrait pas écrire
int tab[1+2];
 
Donc
x = 1 + 2 + y;
sera toujours transformé en 3 + y;
 
Par contre
x = 1 + y + 2;
pas forcément, ça dépend de l'optim.

Reply

Marsh Posté le 08-05-2008 à 22:25:19    

1+y+2 se fait en general optimisé lors de l'etape de CSE

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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