Bonjour à tous et à toutes
j'aimerai bien savoir la signification de la ligne suivante :
Merci d'avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define DSPI_A (*( volatile struct DSPI_tag *) 0xFFF90000)
Bonjour à tous et à toutes
j'aimerai bien savoir la signification de la ligne suivante :
Merci d'avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define DSPI_A (*( volatile struct DSPI_tag *) 0xFFF90000)
Bonjour,
Prenons par étapes :
--> le passage du préprocesseur permet de remplacer DSPI_A par UNE_VALEUR
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define DSPI_A (UNE_VALEUR)
Il est bon de parenthéser la définition de UNE_VALEUR comme fait ici, pour s'assurer que ça va rester un seul morceau lors de l'évaluation et non se mixer avec autre chose. Exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 #define QUATRE 2+2 int a = 2*QUATRE // a devient 2*2+2 = 10 et non 8
L'adresse 0xFFF90000 est caster pour être interpréter comme un pointeur sur TYPE puis on déréférence ce pointeur pour récupérer la valeur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part (*(TYPE *) 0xFFF90000)
TYPE est une structure DSPI_tag. Le qualificatif volatile est une indication pour le compilateur : http://c.developpez.com/faq/?page=va...#VARS_volatile
Code : Sélectionner tout - Visualiser dans une fenêtre à part volatile struct DSPI_tag
Au final :
te permet d'avoir une constante DPSI_A qui vaut la valeur de la structure DSPI_tag qui est à l'adresse 0xFFF90000.
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define DSPI_A (*( volatile struct DSPI_tag *) 0xFFF90000)
Si j'avais eu une explication aussi claire la première fois que j'ai fait de l'embarqué, j'aurais été heureux. Tiens Bktero, attrape ça .
MerciSi j'avais eu une explication aussi claire la première fois que j'ai fait de l'embarqué, j'aurais été heureux. Tiens Bktero, attrape ça
Si on voulait être extrémiste, on pourrait dire que UNE_EXPRESSION s'évaluera en UNE_VALEUR ^^Pour une UNE_VALEUR, pas forcément, mais pour UNE_EXPRESSION, certainement.
UNE_EXPRESSION serait peut-être plus adapté dans le cas général en effet.
Précisons d'ailleurs que si ce qui est intéressant dans la macro est l'ensemble des effets de bord de UNE_EXPRESSION et non UNE_VALEUR qui sera évaluée, on peut mettre des accolades :
Code : Sélectionner tout - Visualiser dans une fenêtre à part #define EXIT_WITH_MESSAGE(msg) {puts(msg); exit(1);}
Bonjour,
Les MACRO ne sont pas remplaçables, mais je pense qu'elles sont trop dangereuses pour pouvoir en en abuser ( A consommer avec modération).
Le c99 introduit le mot clef inline qui permet de faire de la vérification de type à la compilation.
Je préfère (quand cela est possible) systématiquement remplacer les macro par des méthodes inline.
Après le c99 n'est toujours disponible.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 static inline struct DSPI_tag getDSPI_tag() { return *(( volatile struct DSPI_tag *)0xFFF90000); } static inline struct DSPI_tag * getpDSPI_tag() { return ( struct truct DSPI_tag *)0xFFF90000); }
Il est d'usage d'utiliser un do while(0) lorsque l'on écrit une macro composée de plusieurs lignes (statments) ; cela afin de rester le plus largement compatible avec les différents types de C (K&R, 90 ...).
Exactement ; lorsque l'on est cantonné à du C K&R (alias ANSI) ou 90 et que l'on propose une API, on a souvent l'obligation d'utiliser des macros. Un grand classique (notamment en embarqué j'imagine) est de définir des macros permettant à la compilation la vérification de la taille des types employés, de faire des endian swaps, etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #define EXIT_WITH_MESSAGE(msg) do { \ puts(msg); \ exit(1); \ } while(0)
Lorsque ces macros sont bien écrites et bien documentées, je ne vois pas vraiment le danger.
Je ne vois pas bien où est le rapport avec la compatibilité avec les différents types de C.
Le do while(0) est utile lorsqu'on a ce type d'écriture :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 if ( [...] ) EXIT_WITH_MESSAGE(msg); else AUTRE_CHOSE(xxx);
Merci j'ai dit une bêtise. Le #define MACRO {expressions} est a éviter (préférer le do while(0)) pour la raison expliquée dans la doc du précompilateur de GCC : Swallowing the semicolon − The C preprocessor.
Traduction approximative pour nos amis non anglophones :
[L'encapsulation d'expressions entre accolades dans la définition d'une macro] peut poser problème lorsque cette amcro est appelée avant un else, et cela car le point-virgule (;) serait alors considéré comme une expression vide. Supposons le cas suivant :
La présence de deux expressions − la macro d'une part et l'expression nulle (le point-virgule) d'autre part entre le if et le else − en fait un code invalide.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 #define SKIP_SPACES(p, limit) \ { char *lim = (limit); \ while (p < lim) { \ if (*p++ != ' ') { \ p--; break; }}} if (*p != 0) SKIP_SPACES (p, lim); else ...
C'est effectivement ce que tu dis ... Ainsi mieux vaut protéger ses macro d'un do while(0) systématiquement.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager