Si je veux développer une macro C, quels sont les bons moyens de le faire (en plus du suivi manuel)?
Par exemple, GTK_WIDGET_SET_FLAGS
, il utilise une macro qui utilise une macro qui utilise une macro (ou deux) ...
Je veux simplement le voir s’étendre automagiquement d’une manière ou d’une autre, au lieu de rechercher chaque macro, chaque étape du processus.
J'ai essayé cpp, mais il semblait ne faire que le premier passage
sur:
GTK_WIDGET_SET_FLAGS(obj, 13)
J'ai développé le fichier include, puis:
G_STMT_START{ ((GTK_OBJECT_FLAGS (obj)) |= (13)); }G_STMT_END
Cela s’explique par le message d’erreur que j’obtiens ceci sur stderr (lors de l’utilisation du nom de fichier -o)
gtk/gtkwidget.h: 34: 21: gdk/gdk.h: Aucun fichier ou répertoire de ce type gtk/gtkwidget.h: 35: 31: gtk/gtkaccelgroup.h: Aucun fichier ou répertoire de ce type gtk/gtkwidget.h: 36: 27: gtk/gtkobject.h: Aucun fichier ou répertoire de ce type gtk/gtkwidget.h: 37: 31: gtk/gtkadjustment.h: Aucun fichier ou répertoire de ce type gtk /gtkwidget.h:38:26: gtk/gtkstyle.h: Aucun fichier ou répertoire de ce type gtk/gtkwidget.h: 39: 29: gtk/gtksettings.h: Aucun fichier ou répertoire de ce type gtk/gtkwidget .h: 40: 21: atk/atk.h: Aucun fichier ni répertoire de ce type
les répertoires gtk, atk et gdk se trouvent tous dans le répertoire de travail actuel. Comment puis-je laisser cpp y effectuer des recherches?
btw, gcc -E
donne exactement le même résultat que cpp
Le problème du chemin d'inclusion est résolu en utilisant gcc -E et en passant le répertoire d'inclusion avec l'option -I
Selon le compilateur que vous utilisez, il devrait y avoir un moyen de voir le code après que le préprocesseur (qui effectue le développement des macros, les macros ne sont pas du tout connus du compilateur).
Avec gcc, l'option est -E . Voici un exemple simplifié, utilisant du code jouet et non la macro GTK + proprement dite:
~/tmp> cat cpptest.c
#define SET_FLAGS(w, f) ((w)->flags |= (f))
int main(void)
{
SET_FLAGS(0, 4711);
return 0;
}
~/tmp> gcc -E cpptest.c
# 1 "cpptest.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "cpptest.c"
int main(void)
{
((0)->flags |= (4711));
return 0;
}
Dans Visual Studio, vous pouvez générer le fichier d'unité de traduction résultant du préprocesseur. Vous pouvez aller aux options de projet, C/C++/Preprocessor et mettre "Générer un fichier prétraité" ou "Prétraiter dans un fichier" sur Oui (ou utiliser le commutateur/P ou/EP du compilateur pour inclure des numéros de ligne ou non).
Vous pouvez vider le développement d'une macro au moment de l'exécution comme ceci:
#include <stdio.h>
/*
* generic helper macros
*/
#define CALL(macro, arguments) macro arguments
#define STR(...) STR_(__VA_ARGS__)
#define STR_(...) # __VA_ARGS__
/*
* dumps a macro and its expansion to stdout
* the second argument is optional and specifies the number of
* arguments that macro takes: 0 means macro takes zero arguments
* no second argument means macro is not function-like
*/
#define DUMP_MACRO(macro, ...) \
do { \
puts ( \
"'" \
# macro STR(DUMP_MACRO_ARGS_ ## __VA_ARGS__) \
"' expands to '" \
STR(CALL(macro, DUMP_MACRO_ARGS_ ## __VA_ARGS__)) \
"'" \
); \
} while (0)
/* helpers for DUMP_MACRO, add more if required */
#define DUMP_MACRO_ARGS_
#define DUMP_MACRO_ARGS_0 ()
#define DUMP_MACRO_ARGS_1 (<1>)
#define DUMP_MACRO_ARGS_2 (<1>, <2>)
#define DUMP_MACRO_ARGS_3 (<1>, <2>, <3>)
/*
* macros to be used in examples for DUMP_MACRO
*/
#define EXAMPLE ( EXAMPLE0() << 9 )
#define EXAMPLE0() __GNUC__
#define EXAMPLE1(EXAMPLE1) EXAMPLE1
#define EXAMPLE3(EXAMPLE1, _, __) ( EXAMPLE1 ? _(__) : false )
int main() {
/* examples */
DUMP_MACRO(EXAMPLE);
DUMP_MACRO(EXAMPLE0, 0);
DUMP_MACRO(EXAMPLE1, 1);
DUMP_MACRO(EXAMPLE3, 3);
DUMP_MACRO(EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol));
/* does not work for DUMP_MACRO itself, because the
preprocessor does not allow recursion */
DUMP_MACRO(DUMP_MACRO, 1);
DUMP_MACRO(DUMP_MACRO, 2);
return 0;
}
Le programme imprime:
'EXAMPLE' expands to '( 4 << 9 )'
'EXAMPLE0()' expands to '4'
'EXAMPLE1(<1>)' expands to '<1>'
'EXAMPLE3(<1>, <2>, <3>)' expands to '( <1> ? <2>(<3>) : false )'
'EXAMPLE3(EXAMPLE, EXAMPLE1, non_macro_symbol)' expands to '( ( 4 << 9 ) ? non_macro_symbol : false )'
'DUMP_MACRO(<1>)' expands to 'DUMP_MACRO (<1>)'
'DUMP_MACRO(<1>, <2>)' expands to 'DUMP_MACRO (<1>, <2>)'
Cependant, cela ne donne que le full expansion. Si vous avez besoin de simples étapes, Eclipse/CDT peut vous aider, mais uniquement si vous lui apprenez tous les en-têtes et les indicateurs de compilateur utilisés.
gcc -E myfile.c
Si vous utilisez gcc, vous pouvez aussi lancer
cpp myfile.c
De nombreux IDE vous montreront la version développée de la macro dans l'éditeur lorsque le pointeur de la souris passe au-dessus de l'identifiant (ou d'une autre manière). Je sais que Eclipse/CDT le fait, et Visual Studio le fait (au moins, VS 2008 le fait).
Il peut être utile de faire en sorte que le compilateur génère une sortie prétraitée si vous recherchez un problème épineux, mais utilisez-le jour après jour pour savoir ce qui se passe avec le code sur votre écran, en utilisant le IDE est le chemin à parcourir.
gcc même avec -E a besoin du chemin des fichiers d'en-tête ... comme -I _path_to_your_headers ...
Si vous avez un Makefile, en général, ce que vous pourriez faire est de surcharger CC avec gcc -E
Généralement, cpp n'est qu'un script qui ajoute des indicateurs à gcc pour le préprocesseur, comme d'habitude ...
Vous voulez exécuter uniquement l’étape preprocessor de votre compilateur, chargée de l’extension des macros. Pour gcc
, il s'agit de "gcc -E", mais je ne suis pas sûr des autres compilateurs.
Essayez d’exécuter cpp sur votre fichier source
Avez-vous essayé d'exécuter gcc -E plusieurs fois jusqu'à ce qu'il n'y ait plus de macros?
Lorsque piégé dans un IDE sommaire, essayez quelque chose comme
#define DISPLAY_VALUE2(x) #x
#define DISPLAY_VALUE(x) DISPLAY_VALUE2(x)
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
produire
…/sketch_may21a.ino: In function 'void loop()':
…/sketch_may21a.ino:10:54: note: #pragma message: #DEFINE F_CPU 16000000L
#pragma message("#DEFINE F_CPU " DISPLAY_VALUE(F_CPU))
^
grâce à "mdematos" sur http://MicroChip.com/forums/m724722.aspx