#1 Le 10/05/2008, à 01:57
- Zouk
C : préprocesseur avec certaines options
Bonjour à tous,
Je dois réaliser un module générique qui n'ai pas à s'appuyer sur un seul type. J'ai donc choisis de faire un script qui génère un nouveau module pour chaque type différent.
Je cherche donc un préprocesseur qui me permette de garder les commentaires et de ne pas "inclure" les include (garder la ligne et ne pas la remplacer par le texte de l'include).
Je viens de passer une heure à fouiller toutes les options de cpp, et j'arrive pas à l'empêcher d'inclure les #include, quelqu'un sait-il comment faire ?
En gros, j'aimerais un préprocesseur qui me transforme
// Salut
#include <stdio.h>
#ifdef TOTO
tata ;
#else
Hello ;
#endif
en
//Salut
#include <stdio.h>
Hello ;
Ca se fait ca ?
Hors ligne
#2 Le 10/05/2008, à 03:11
- Le Farfadet Spatial
Re : C : préprocesseur avec certaines options
Salut à tous !
Ca se fait ca ?
Oui, ça se fait. Ton exemple le fait, d'ailleurs... Si tu veux éviter d'inclure un en-tête dans certains cas, essaie ceci :
// Salut
#ifdef TOTO
tata ;
#else
#include <stdio.h>
Hello ;
#endif
En fait, on a très souvent recourt à l'inclusion conditionnelle, puisque c'est le moyen de protéger ses en-têtes. Par exemple, le fichier « interfaces.h » a tout intérêt à être de cette forme :
#ifndef INTERFACES_H
#define INTERFACES_H
#include <stdio.h> // ou n'importe quel autre en-tête, ou aucun #include
// code
#endif // #ifndef INTERFACES_H
Cela dit, je pense que ton exemple et ton approche sont tordus et que tu ne devrais pas l'utiliser. En C, pour faire une fonction générique (indépendante du type), on a recourt aux pointeurs de type *void. Cela dit, un passage de ton message me met la puce à l'oreille :
Je viens de passer une heure à fouiller toutes les options de cpp, et j'arrive pas à l'empêcher d'inclure les #include, quelqu'un sait-il comment faire ?
cpp ? Ne ferais-tu pas plutôt du C++ ? Auquel cas ce sont des modèles (template) qu'il te faut utiliser.
À bientôt.
Le Farfadet Spatial
Hors ligne
#3 Le 10/05/2008, à 08:25
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
En C, pour faire une fonction générique (indépendante du type), on a recourt aux pointeurs de type *void.
Pas forcément, d'ailleurs la norme du C définit elle même, un tas de macro pour du traitement générique (notamment pour les calculs mathématiques sur des réels).
Hors ligne
#4 Le 10/05/2008, à 08:28
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
En C, pour faire une fonction générique (indépendante du type), on a recourt aux pointeurs de type *void.
C'est faux! on a recourt au type void *, encore appeler pointeur générique ou pointeur sur void (même je n'aime pas cette dernière).
Hors ligne
#5 Le 10/05/2008, à 16:53
- Zouk
Re : C : préprocesseur avec certaines options
Non, je suis bien en C même si cpp peut compiler du C++.
Une autre facon de faire un module générique, c'est de faire un script qui modifie sont nom ainsi que le nom des sous-programmes en fonctions des variables. Le problème c'est que pour générer un .h "propre", je voudrai supprimer tout ce qui ne sert pas mais ne pas inclure les f"include". D'où ma question.
Donc est-ce que quelqu'un sait si il existe un préprocesseur ou une option de cpp qui me permette de ne pas include les include et de garder la ligne #include machin.h intacte ?
Merci
Edith : en fait non cpp ne peut pas compiler du C++ après vérification, je pensais qu'on utilisait le préprocesseur d'un éditeur C++ mais cpp est juste un préprocesseur en fait.
Dernière modification par Zouk (Le 12/05/2008, à 01:13)
Hors ligne
#6 Le 10/05/2008, à 19:01
- Link31
Re : C : préprocesseur avec certaines options
Je viens de passer une heure à fouiller toutes les options de cpp, et j'arrive pas à l'empêcher d'inclure les #include, quelqu'un sait-il comment faire ?
cpp ? Ne ferais-tu pas plutôt du C++ ? Auquel cas ce sont des modèles (template) qu'il te faut utiliser.
cpp, c'est le C PreProcessor
À mon avis, le fait que CPP fasse penser au C++ vient du fait qu'on a souvent préféré utiliser des caractères "standards" pour désigner le C++ (pour éviter des erreurs d'analyse, de regex...). D'où le .cpp. Mais CPP est bien le nom du préprocesseur à l'origine.
Et on trouve toujours (inconsciemment ?) un prétexte pour conseiller le C++ à la place du C, n'est-ce pas ?
Hors ligne
#7 Le 11/05/2008, à 09:02
- Le Farfadet Spatial
Re : C : préprocesseur avec certaines options
Salut à tous !
Et on trouve toujours (inconsciemment ?) un prétexte pour conseiller le C++ à la place du C, n'est-ce pas ?
Bon, je me suis enflammé sur le nom du préprocesseur.
Sinon, non, je ne cherchais pas à conseiller à Zouk de passer au C++, c'est juste que s'il avait utilisé le C++, alors les templates sont là pour ça.
D'accord pour la généricité, je voulais juste dire que personnellement je conseille plutôt le void*.
Sinon, je ne comprends pas ta question, Zouk, si ce que je t'ai donné ne correspond pas...
À bientôt.
Le Farfadet Spatial
Hors ligne
#8 Le 11/05/2008, à 19:51
- Zouk
Re : C : préprocesseur avec certaines options
En fait, il y a deux techniques pour faire de la généricité : les void* (lourd et dangereux) ou générer des modules différents à partir d'un script : en gros un script modifie (avec des instructions préprocesseur) certaines partie du code.
Il me faudrait donc résoudre certaines parties des instructions du préprocesseur (les if else en gros) pour qu'il me donne le code final. Mais je voudrai qu'il garde
-les commentaires
-les include (qu'il me mettre pas tout le code des fichiers inclus et qu'il me laisse le #include ...).
Le problème c'est que je n'arrive pas à faire ca avec les options de cpp. Savez-vous comment faire ?
Hors ligne
#9 Le 11/05/2008, à 23:39
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
les void* (lourd et dangereux)
très très discutable!!!
Hors ligne
#10 Le 12/05/2008, à 01:11
- Zouk
Re : C : préprocesseur avec certaines options
Ouais, peut être que je changerais d'avis après avoir essayé ca mais les void* c'est une prise de tête phénoménale et j'ai pas envie de m'y lancer tout de suite.
Personne pour les options de cpp ?
Hors ligne
#11 Le 12/05/2008, à 01:22
- nicolas66
Re : C : préprocesseur avec certaines options
Je connais pas en détail les options de `gcc' mais ya moyen de récupérer le résultat du préprocesseur avec :
gcc -E foo.c
Par contre, je doute qu'on puisse demander à garder les commentaires et les directives d'inclusion #include.
très très discutable!!!
[hs]A mon sens, les void* sont plus dangereux que les templates car ils impliquent une allocation mémoire et des casts. Ils sont donc davantage source d'erreurs.[/hs]
Dernière modification par nicolas66 (Le 12/05/2008, à 01:33)
"The computer was born to solve problems that did not exist before." (B. Gates)
Hors ligne
#12 Le 12/05/2008, à 08:41
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
[hs]A mon sens, les void* sont plus dangereux que les templates car ils impliquent une allocation mémoire et des casts. Ils sont donc davantage source d'erreurs.[/hs]
ça montre ton niveau : en C, on ne caste pas un pointeur générique!!!!
ce code est parfaitement valide en C :
int a = 5;
int *p1 = &a;
void *pg = pa;
int *p2 = pg;
printf ("%d\n", *p2);
Hors ligne
#13 Le 12/05/2008, à 10:58
- Seren
Re : C : préprocesseur avec certaines options
ça montre ton niveau : en C, on ne caste pas un pointeur générique!!!!
ce code est parfaitement valide en C :
Est-ce que tu peux détailler ce que tu veux dire par là ? Tu veux dire qu'on ne fait pas de cast explicite ou tu parles de bonnes pratiques ? J'avoue que je comprends pas très bien ce que tu dis et pourquoi, et comme ça a l'air important, j'aimerais comprendre .
"I am not young enough to know everything". Oscar Wilde
Hors ligne
#14 Le 12/05/2008, à 11:02
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
un exemple vaut mieux qu'un long discours :
int *p = (int*)malloc (sizeof *p);
malloc retourne un pointeur générique, le cast ne sert strictement à rien.
int *p = malloc (sizeof *p);
Hors ligne
#15 Le 12/05/2008, à 12:00
- Le Farfadet Spatial
Re : C : préprocesseur avec certaines options
Salut à tous !
Zouk a écrit :les void* (lourd et dangereux)
très très discutable!!!
Que oui, je suis tout à fait d'accord avec Nicolas Sitbon !
A mon sens, les void* sont plus dangereux que les templates car ils impliquent une allocation mémoire et des casts. Ils sont donc davantage source d'erreurs.
Au-delà du fait qu'il n'est en effet pas besoin de faire une conversion sur les pointeurs génériques en C, tu as raison : les modèles (template) sont plus sécurisés. Cependant, c'est du C++ et non pas du C.
Il me faudrait donc résoudre certaines parties des instructions du préprocesseur (les if else en gros) pour qu'il me donne le code final. Mais je voudrai qu'il garde
-les commentaires
-les include (qu'il me mettre pas tout le code des fichiers inclus et qu'il me laisse le #include ...).
Je peux me tromper, mais si je comprends bien, ce que tu cherches à faire, c'est de la méta-programmation, c'est-à-dire donner des éléments au préprocesseur pour qu'il produise ensuite du code. Personnellement, pour faire de la méta-programmation, soit je me tourne vers le Lisp ou bien le Prolog ou encore le C++, soit j'utilise Flex et Bison, mais je n'utilise pas le C tel quel.
Sinon, pour de la programmation avec pointeurs génériques, je te conseille cet ouvrage :
Kyle LOUDON, Maîtrise des Algorithmes en C, O'Reilly.
Pour de la programmation générique en C en utilisant les macro-commandes, tu peux jeter un œil sur la SGLIB : http://sglib.sourceforge.net/. Je dois reconnaître que je n'ai pas testé cette dernière.
À bientôt.
Le Farfadet Spatial
Hors ligne
#16 Le 12/05/2008, à 14:09
- nicolas66
Re : C : préprocesseur avec certaines options
ça montre ton niveau : en C, on ne caste pas un pointeur générique!!!!
ce code est parfaitement valide en C
Oui c'est vrai qu'éviter les casts est plus sécurisé. En revanche, l'écriture me paraît un tantinet lourd comparés aux templates
"The computer was born to solve problems that did not exist before." (B. Gates)
Hors ligne
#17 Le 12/05/2008, à 14:49
- Le Farfadet Spatial
Re : C : préprocesseur avec certaines options
Salut à tous !
En revanche, l'écriture me paraît un tantinet lourd comparés aux templates
Certainement. Mais les modèles restent du C++ et là, il s'agit de C...
À bientôt.
Le Farfadet Spatial
Hors ligne
#18 Le 12/05/2008, à 15:14
- Link31
Re : C : préprocesseur avec certaines options
ça montre ton niveau : en C, on ne caste pas un pointeur générique!!!!
En C pre-ANSI il fallait le caster. Et si on veut intégrer le code à du C++, il faut aussi le caster.
Donc si on sait ce qu'on fait (c-à-d si on n'oublie pas d'inclure stdlib.h), ça ne peut pas faire de mal.
Hors ligne
#19 Le 12/05/2008, à 15:19
- nicolas66
Re : C : préprocesseur avec certaines options
Certainement. Mais les modèles restent du C++ et là, il s'agit de C...
J'entends bien. J'exprimais simplement mon point de vue
"The computer was born to solve problems that did not exist before." (B. Gates)
Hors ligne
#20 Le 12/05/2008, à 15:23
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
nicolas.sitbon a écrit :ça montre ton niveau : en C, on ne caste pas un pointeur générique!!!!
En C pre-ANSI il fallait le caster. Et si on veut intégrer le code à du C++, il faut aussi le caster.
Donc si on sait ce qu'on fait (c-à-d si on n'oublie pas d'inclure stdlib.h), ça ne peut pas faire de mal.
En C pré ansi, il n'y avait pas de pointeur générique, à la place on utilisait "char*".
Intégrer du C dans du C++, ça montre encore le niveau, ce sont deux langages différents, et le C n'est pas un sous ensemble de C++, grosse erreur!
Dire que ça ne peut pas faire de mal relève encore de l'ignorance, le fait de caster explicitement empêche le compilateur de produire un avertissement en cas de changement futur (et oui faut aussi penser à l'avenir).
Hors ligne
#21 Le 12/05/2008, à 18:19
- snapshot
Re : C : préprocesseur avec certaines options
Pour revenir au problème initial, ce que tu cherches est en fait un pré-préprocesseur...
Il y m4 qui est puissant et peu connu. Si tu l'utilises, tu t'embarques en dehors des sentiers battus. Je ne connais pas de projet C qui l'utilise en tant que pré-préprocesseur (en dehors du fameux ./configure), mais pourquoi pas ? Il s'intégre parfaitement bien dans une règle Makefile.
Pour ton define donné en exemple :
fichier source.m4
#include <stdio.h>
M4_macro;
ensuite (à mettre dans le Makefile) :
m4 -P -DM4_macro='tata()' source.m4 > source_tata.c
m4 -P -DM4_macro='toto()' source.m4 > source_toto.c
Le -P oblige m4 à préfixer ces macros avec "m4_", car sinon, on court le risque d'avoir des conflits de noms avec des macros pré-définies de m4, comme mkstemp() qui est à la fois une macro et une fonction C standard.
et pour aller plus loin :
m4_define(M4_swap,
void swap_$1($1 *a, $1 *b) {
$1 exch;
exch=*a;
*a=*b;
*b=exch;
})
M4_swap(int);
M4_swap(long);
M4_swap(float);
qui donnera avec m4 -P swap.m4
void swap_int(int *a, int *b) {
int exch;
exch=*a;
*a=*b;
*b=exch;
};
void swap_long(long *a, long *b) {
long exch;
exch=*a;
*a=*b;
*b=exch;
};
void swap_float(float *a, float *b) {
float exch;
exch=*a;
*a=*b;
*b=exch;
};
Tu peux faire une règle générique dans le Makefile :
%: %.m4
m4 -P $< > $@
Ensuite, tu n'as plus qu'à nommer tes fichiers à pré-préprocesser en "fichier.m4" et à t'inspirer de ce Makefile :
truc.c: truc.m4
machin.c: machin.m4
truc.o: truc.c
machin.o: machin.c
programe: truc.o machin.o
Pensez à mettre [Résolu] dans le titre une fois votre problème réglé !
Hors ligne
#22 Le 12/05/2008, à 18:48
- Link31
Re : C : préprocesseur avec certaines options
Intégrer du C dans du C++, ça montre encore le niveau, ce sont deux langages différents, et le C n'est pas un sous ensemble de C++, grosse erreur!
Dire que ça ne peut pas faire de mal relève encore de l'ignorance, le fait de caster explicitement empêche le compilateur de produire un avertissement en cas de changement futur (et oui faut aussi penser à l'avenir).
Un petit conseil quand même, évite de parler comme ça à des gens que tu ne connais absolument pas. Niveau ? Ignorance ? Je trouve ça un peu présomptueux. Surtout qu'autant que je sache, je suis bien l'une des dernières personnes sur ce forum susceptible de se voir donner des leçons de C/C++, en particulier par des gens comme toi (=une personne quelconque, du moins jusqu'à ce que tu me montres ton expérience)...
Hors ligne
#23 Le 12/05/2008, à 18:55
- nicolas.sitbon
Re : C : préprocesseur avec certaines options
Moi je m'appuie sur des personnes qui ont fait leur preuve, et je t'assure que quand je dis une bêtise, elle ne manque pas de me rappeler à l'ordre. En l'occurrence, tu as dis une bêtise, il est normal que je te reprenne. Le C n'est pas un langage pour débutant, et je dirais que tout le monde est susceptible de se voir donner les leçons de C (encore une fois je ne parle pas de C++ qui n'a rien à voir), peut être toi le premier pour avoir dis que ça ne faisait pas de mal de caster un pointeur générique...
Hors ligne
#24 Le 12/05/2008, à 19:27
- Pygnol
Re : C : préprocesseur avec certaines options
Et si on veut intégrer le code à du C++, il faut aussi le caster.
Dans ce cas, pourquoi ne pas simplement le lier?
Le C n'est pas un langage pour débutant, et je dirais que tout le monde est susceptible de se voir donner les leçons de C (encore une fois je ne parle pas de C++ qui n'a rien à voir), peut être toi le premier pour avoir dis que ça ne faisait pas de mal de caster un pointeur générique...
Le sujet a déjà été discuté à de nombreuses reprises. Il me semble que le consensus est qu'il est idiomatique en C de ne pas caster e.g. la valeur retournée par malloc(). Il peut certes y avoir quelques soucis en cas d'oubli de stdlib.h, mais est-ce réellement chose courante ?
Personnellement, lorsque je code dans un langage, j'essaie d'utiliser un style le plus idiomatique possible. On ne va pas itérer sur une liste en Python à l'aide d'une boucle while sous prétexte d'on fait pareil en C. De la même manière, je trouve étrange de caster la valeur retournée par malloc() sous prétexte qu'on veut rendre le code compatible avec C++. Il y a suffisamment d'incompatibilités entre ces deux langages pour pouvoir affirmer que c'est une mauvaise idée, en général.
Thierry
Dernière modification par Pygnol (Le 12/05/2008, à 19:37)
Hors ligne