À nouveau, ce n'est pas ton problème c'est la solution que
un programme séparé en fonction d'une configuration, une
utilisation plus masquante des macros dans le genre
À nouveau, ce n'est pas ton problème c'est la solution que
un programme séparé en fonction d'une configuration, une
utilisation plus masquante des macros dans le genre
À nouveau, ce n'est pas ton problème c'est la solution que
un programme séparé en fonction d'une configuration, une
utilisation plus masquante des macros dans le genre
Harpo wrote:
D'abord merci pour ta réponse et ta solution à base d'unions.Soit c'est su au moment de la compilation du programme, auquel cas on
peut utiliser le préprocesseur, mais on peut se demander s'il ne vaut
pas mieux faire 3 programmes et des fonctions communes au 3
programmes.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Aujourd'hui, j'ai environ 40 "maisons" différentes.
Pour répondre à la
demande de Jean-Marc Bourguet (post récent plus haut dans ce thread),
voici mon problème.
En fait mes maisons sont des architectures de véhicules différentes,
avec on sans batterie, avec ou sans moteur électrique, hybride série,
parallèle, ou série-parallèle (par exemple, il y a bien d'autres
options). Le programme utilise la programmation dynamique (principe de
Bellman) pour optimiser la consommation de carburant sur un cycle
vitesse/temps connu par avance (c'est pourquoi j'ai tout intérêt à ce
que le programme soit optimisé, c'est gourmand en mémoire et en temps
de calcul). J'ai bien découpé mon programme en diverses fonctions.
Mais suivant l'architecture de véhicule considérée parmi les 40, des
différences apparaissent un peu partout, dont j'ai tenu compte avec
mes #if defined(...).
Dans un fichier parameters.h de mon projet, il y a le #define VEHICLE
23 (par exemple véhicule 23) qui permet de compiler le projet avec la
bonne architecture.
Avec ta solution à base d'unions ou les autres proposées, je trouve
que les choses ne sont pas forcément plus simples (peut-être un peu
plus lisible mais moins intuitif). Mais je me trompe peut-être.
L'idée de mon post initial était donc de me débarrasser des #ifdef, là
où peut-être ce serait possible;
Harpo wrote:
D'abord merci pour ta réponse et ta solution à base d'unions.
Soit c'est su au moment de la compilation du programme, auquel cas on
peut utiliser le préprocesseur, mais on peut se demander s'il ne vaut
pas mieux faire 3 programmes et des fonctions communes au 3
programmes.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Aujourd'hui, j'ai environ 40 "maisons" différentes.
Pour répondre à la
demande de Jean-Marc Bourguet (post récent plus haut dans ce thread),
voici mon problème.
En fait mes maisons sont des architectures de véhicules différentes,
avec on sans batterie, avec ou sans moteur électrique, hybride série,
parallèle, ou série-parallèle (par exemple, il y a bien d'autres
options). Le programme utilise la programmation dynamique (principe de
Bellman) pour optimiser la consommation de carburant sur un cycle
vitesse/temps connu par avance (c'est pourquoi j'ai tout intérêt à ce
que le programme soit optimisé, c'est gourmand en mémoire et en temps
de calcul). J'ai bien découpé mon programme en diverses fonctions.
Mais suivant l'architecture de véhicule considérée parmi les 40, des
différences apparaissent un peu partout, dont j'ai tenu compte avec
mes #if defined(...).
Dans un fichier parameters.h de mon projet, il y a le #define VEHICLE
23 (par exemple véhicule 23) qui permet de compiler le projet avec la
bonne architecture.
Avec ta solution à base d'unions ou les autres proposées, je trouve
que les choses ne sont pas forcément plus simples (peut-être un peu
plus lisible mais moins intuitif). Mais je me trompe peut-être.
L'idée de mon post initial était donc de me débarrasser des #ifdef, là
où peut-être ce serait possible;
Harpo wrote:
D'abord merci pour ta réponse et ta solution à base d'unions.Soit c'est su au moment de la compilation du programme, auquel cas on
peut utiliser le préprocesseur, mais on peut se demander s'il ne vaut
pas mieux faire 3 programmes et des fonctions communes au 3
programmes.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Aujourd'hui, j'ai environ 40 "maisons" différentes.
Pour répondre à la
demande de Jean-Marc Bourguet (post récent plus haut dans ce thread),
voici mon problème.
En fait mes maisons sont des architectures de véhicules différentes,
avec on sans batterie, avec ou sans moteur électrique, hybride série,
parallèle, ou série-parallèle (par exemple, il y a bien d'autres
options). Le programme utilise la programmation dynamique (principe de
Bellman) pour optimiser la consommation de carburant sur un cycle
vitesse/temps connu par avance (c'est pourquoi j'ai tout intérêt à ce
que le programme soit optimisé, c'est gourmand en mémoire et en temps
de calcul). J'ai bien découpé mon programme en diverses fonctions.
Mais suivant l'architecture de véhicule considérée parmi les 40, des
différences apparaissent un peu partout, dont j'ai tenu compte avec
mes #if defined(...).
Dans un fichier parameters.h de mon projet, il y a le #define VEHICLE
23 (par exemple véhicule 23) qui permet de compiler le projet avec la
bonne architecture.
Avec ta solution à base d'unions ou les autres proposées, je trouve
que les choses ne sont pas forcément plus simples (peut-être un peu
plus lisible mais moins intuitif). Mais je me trompe peut-être.
L'idée de mon post initial était donc de me débarrasser des #ifdef, là
où peut-être ce serait possible;
Maintenant, afin de voir un peu de code et m'en inspirer, je repose ma
question: auriez-vous un projet sous Linux à me conseiller, dont je
pourrais lire le code? Un projet où le même type de problème se poserait, à
savoir une structure "à géométrie variable" avec juste ce qu'il faut
suivant le choix de l'utilisateur.
Maintenant, afin de voir un peu de code et m'en inspirer, je repose ma
question: auriez-vous un projet sous Linux à me conseiller, dont je
pourrais lire le code? Un projet où le même type de problème se poserait, à
savoir une structure "à géométrie variable" avec juste ce qu'il faut
suivant le choix de l'utilisateur.
Maintenant, afin de voir un peu de code et m'en inspirer, je repose ma
question: auriez-vous un projet sous Linux à me conseiller, dont je
pourrais lire le code? Un projet où le même type de problème se poserait, à
savoir une structure "à géométrie variable" avec juste ce qu'il faut
suivant le choix de l'utilisateur.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Je pense qu'il pourrait peut-être être bon de réflêchir encore à cela.
Cela passe par l'analyse de ce qui est spécifique à un vehicule et de
ce qui est commun à chaque véhicule.
A moins d'avoir un projet trivial (on écrit, on utilise et on jette dans
la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tous ces tests sur le véhicule sont-ils dans des endroits du programme
où la question de performance est importante (dans des boucles
fortement imbriquées) ?
Il faut dans ce cas privilégier ce qui est fait à la compile par rapport
à ce qui est dynamiquement fait à l'exécution. i.e. on n'en a rien à
foutre de passer 1 seconde à compiler un programme si son exécution
passe de 2 heures à 1 heure.
ratio = x->motor_ratio + get_turbo_ratio( x ) ;
Amha, cela permet de séparer les problèmes. Si on n'est pas sensible à
l'esthétique, on peut aussi se dire qu'en cas de changement dans les
données relatives aux voitures, il n'y a qu'un source à modifier sans
avoir à modifier ce qui n'est pas en rapport direct avec cette modif,
comme l'implémentation d'algo.
Note :
Si tu utilises GNU/Linux (merci de ne pas oublier 'GNU'), tu utilises
aussi probablement GCC, tu n'as pas besoin de modifier le source pour
mettre :
#define VEHICLE MASSEY_FERGUSSON
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Je pense qu'il pourrait peut-être être bon de réflêchir encore à cela.
Cela passe par l'analyse de ce qui est spécifique à un vehicule et de
ce qui est commun à chaque véhicule.
A moins d'avoir un projet trivial (on écrit, on utilise et on jette dans
la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tous ces tests sur le véhicule sont-ils dans des endroits du programme
où la question de performance est importante (dans des boucles
fortement imbriquées) ?
Il faut dans ce cas privilégier ce qui est fait à la compile par rapport
à ce qui est dynamiquement fait à l'exécution. i.e. on n'en a rien à
foutre de passer 1 seconde à compiler un programme si son exécution
passe de 2 heures à 1 heure.
ratio = x->motor_ratio + get_turbo_ratio( x ) ;
Amha, cela permet de séparer les problèmes. Si on n'est pas sensible à
l'esthétique, on peut aussi se dire qu'en cas de changement dans les
données relatives aux voitures, il n'y a qu'un source à modifier sans
avoir à modifier ce qui n'est pas en rapport direct avec cette modif,
comme l'implémentation d'algo.
Note :
Si tu utilises GNU/Linux (merci de ne pas oublier 'GNU'), tu utilises
aussi probablement GCC, tu n'as pas besoin de modifier le source pour
mettre :
#define VEHICLE MASSEY_FERGUSSON
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
C'est ce à quoi j'avais pensé par un moment.
Seulement, pour chacune des "maisons" correspondant à chacun des
programmes, les fonctions se seraient drôlement ressemblées.
Franchement, il aurait été très dur voire impossible de faire des
fonctions communes de manière à ne pas avoir de redondances.
Je pense qu'il pourrait peut-être être bon de réflêchir encore à cela.
Cela passe par l'analyse de ce qui est spécifique à un vehicule et de
ce qui est commun à chaque véhicule.
A moins d'avoir un projet trivial (on écrit, on utilise et on jette dans
la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tous ces tests sur le véhicule sont-ils dans des endroits du programme
où la question de performance est importante (dans des boucles
fortement imbriquées) ?
Il faut dans ce cas privilégier ce qui est fait à la compile par rapport
à ce qui est dynamiquement fait à l'exécution. i.e. on n'en a rien à
foutre de passer 1 seconde à compiler un programme si son exécution
passe de 2 heures à 1 heure.
ratio = x->motor_ratio + get_turbo_ratio( x ) ;
Amha, cela permet de séparer les problèmes. Si on n'est pas sensible à
l'esthétique, on peut aussi se dire qu'en cas de changement dans les
données relatives aux voitures, il n'y a qu'un source à modifier sans
avoir à modifier ce qui n'est pas en rapport direct avec cette modif,
comme l'implémentation d'algo.
Note :
Si tu utilises GNU/Linux (merci de ne pas oublier 'GNU'), tu utilises
aussi probablement GCC, tu n'as pas besoin de modifier le source pour
mettre :
#define VEHICLE MASSEY_FERGUSSON
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
c'est le C le plus immonde que j'ai jamais vu...
même à 100 euro de l'heure, je debeugue pas un truc comme ça...
les bazars dans chaque case se ressemblent beaucoup ? et alors ?
aucune importance, tu as du C lisible, clair et maintenable...
c'est le C le plus immonde que j'ai jamais vu...
même à 100 euro de l'heure, je debeugue pas un truc comme ça...
les bazars dans chaque case se ressemblent beaucoup ? et alors ?
aucune importance, tu as du C lisible, clair et maintenable...
c'est le C le plus immonde que j'ai jamais vu...
même à 100 euro de l'heure, je debeugue pas un truc comme ça...
les bazars dans chaque case se ressemblent beaucoup ? et alors ?
aucune importance, tu as du C lisible, clair et maintenable...
Mais *il n'y a pas de bug* (jusqu'à preuve du contraire)... 100% sane avec
Valgrind, et il fait exactement ce qu'on lui dit.
Si j'obtiens du code qui se répète d'un case à l'autre, cela veut dire que
si je dois faire une modif (algorithmique, j'entends) dans un case, je
dois
le faire dans tous les autres. Cela n'est-il pas source d'erreur? Ça ne me
paraît pas génial pour la maintenance...
En plus, quand y'a 500 lignes dans chaque case, c'est un peu lourd...
Je pense qu'il serait possible de faire sans constantes préprocesseur,
mais
alors il faudrait encore découper plein de fonctions.
Ce serait un
découpage pas évident, et qui ne pouvait être fait que difficilement lors
de la conception (si, réellement).
Mais *il n'y a pas de bug* (jusqu'à preuve du contraire)... 100% sane avec
Valgrind, et il fait exactement ce qu'on lui dit.
Si j'obtiens du code qui se répète d'un case à l'autre, cela veut dire que
si je dois faire une modif (algorithmique, j'entends) dans un case, je
dois
le faire dans tous les autres. Cela n'est-il pas source d'erreur? Ça ne me
paraît pas génial pour la maintenance...
En plus, quand y'a 500 lignes dans chaque case, c'est un peu lourd...
Je pense qu'il serait possible de faire sans constantes préprocesseur,
mais
alors il faudrait encore découper plein de fonctions.
Ce serait un
découpage pas évident, et qui ne pouvait être fait que difficilement lors
de la conception (si, réellement).
Mais *il n'y a pas de bug* (jusqu'à preuve du contraire)... 100% sane avec
Valgrind, et il fait exactement ce qu'on lui dit.
Si j'obtiens du code qui se répète d'un case à l'autre, cela veut dire que
si je dois faire une modif (algorithmique, j'entends) dans un case, je
dois
le faire dans tous les autres. Cela n'est-il pas source d'erreur? Ça ne me
paraît pas génial pour la maintenance...
En plus, quand y'a 500 lignes dans chaque case, c'est un peu lourd...
Je pense qu'il serait possible de faire sans constantes préprocesseur,
mais
alors il faudrait encore découper plein de fonctions.
Ce serait un
découpage pas évident, et qui ne pouvait être fait que difficilement lors
de la conception (si, réellement).
c'est étonnant comme tu as un problème de conception et de vision globale
de ton projet...
tu dois avoir une très grosse habitude de pondre du C au fil de l'eau...
je sais, ça pique les doigts pour un programmeur mais pour ton projet,
il faut passer une semaine avec juste un papier et un crayon...
et tu ne dessineras que des rectangles et des flèches...
c'est étonnant comme tu as un problème de conception et de vision globale
de ton projet...
tu dois avoir une très grosse habitude de pondre du C au fil de l'eau...
je sais, ça pique les doigts pour un programmeur mais pour ton projet,
il faut passer une semaine avec juste un papier et un crayon...
et tu ne dessineras que des rectangles et des flèches...
c'est étonnant comme tu as un problème de conception et de vision globale
de ton projet...
tu dois avoir une très grosse habitude de pondre du C au fil de l'eau...
je sais, ça pique les doigts pour un programmeur mais pour ton projet,
il faut passer une semaine avec juste un papier et un crayon...
et tu ne dessineras que des rectangles et des flèches...
A moins d'avoir un projet trivial (on écrit, on utilise et on jette
dans la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tu veux dire que la plupart du temps, sur les gros projets, les
programmeurs commencent à coder tout de suite?
Tous ces tests sur le véhicule sont-ils dans des endroits du
programme où la question de performance est importante (dans des
boucles fortement imbriquées) ?
Pas forcément. La réponse est plutôt non.
[...]ratio = x->motor_ratio + get_turbo_ratio( x ) ;
(...)
Je suis d'accord, mais cela peut rendre le .h compliqué dans mon cas
(voir plus bas).
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
Jusqu'à maintenant je faisais un sed -i "s///" sur le fichier
parameters.h.
J'ai recensé (j'aurais peut-être dû le faire dès le début) les
endroits où les constantes préprocesseur interviennent:
1///////// Prototypes de fonction. Effectivement ce n'est pas très
lisible ;-)
D'après ce que vous m'avez tous indiqué, je vois trois solutions:
- passer tous les paramètres, et s'occuper d'un plus ou moins grand
nombre de ceux-ci dans la fonction (il va quand même falloir regarder
à l'intérieur dans quel cas on est pour appliquer telle ou telle
instruction).
- faire plusieurs programmes pour autant de véhicule avec une fonction
f_graph_return différente à chaque fois (dur pour la maintenance si un
changement général dans f_graph_solve apparaissait);
- définir le prototype avec une macro préprocesseur dans le .c,
celle-ci étant définie dans le .h (juste pour la lisibilité, mais il
reste à rendre aussi lisible le corps de la fonction).
static void f_graph_return(struct graph gr
,struct results * res
,struct transmission trans
#if !defined(ELECTRIC_GENERATOR)
,struct internal_combustion_engine ice
#endif /* !defined(ELECTRIC_GENERATOR) */
2////////// Dans le corps des fonctions.
Voici deux exemples extraits de la fonction évoquée précédemment. J'ai
enlevé les commentaires (qui sont en assez grande quantité...).
Pas évident de mettre cela dans le .h, surtout que si je dois faire
comme ça à chaque fois, le .h risque de devenir gros ;-)
-------- 1er extrait
#if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING))
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0)
&& ABOUT_EQUAL_2(initial_acc_p_elec,0) )
{
it2max=1;
}
#else
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0) )
{
it2max=1;
}
#endif /* if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING)) */
---------- fin du premier extrait.
---------- 2ième extrait
#ifdef STOP_POSSIBILITY
int it;
for(it=0;it<10;it++)
{
printf("nItération %i.n",it);
#endif /* ifdef STOP_POSSIBILITY */
--------- fin du 2ième extrait
(le for est refermé plus loin).
Alors pour la libération, on pourrait peut-être imaginer initialiser
les pointeurs à NULL (actuellement j'ai une fonction d'allocation qui
réserve la mémoire, et par exemple pour un vecteur de réels, les
initialise à 0.0/0.0, i.e. NAN). Si le pointeur est resté à NULL,
c'est qu'il n'a pas été initialisé, on ne le libère pas. Ainsi on
pourrait libérer systématiquement tous les pointeurs dans une fonction
par structure. Est-ce une bonne solution?
En revanche pour l'allocation, soit on garde les constantes
préprocesseur, soit on utilise un enumération, mais ça revient à peu
près au même je trouve, sauf que avec les enum, il va falloir que le
type de véhicule soit passé en ligne de commande du programme (car je
ne vais pas le changer en dur dans les source .c ou .h à chaque fois
que je change de véhicule, et recompiler ensuite, autant utiliser une
constante préprocesseur à ce compte-là).
A moins d'avoir un projet trivial (on écrit, on utilise et on jette
dans la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tu veux dire que la plupart du temps, sur les gros projets, les
programmeurs commencent à coder tout de suite?
Tous ces tests sur le véhicule sont-ils dans des endroits du
programme où la question de performance est importante (dans des
boucles fortement imbriquées) ?
Pas forcément. La réponse est plutôt non.
[...]
ratio = x->motor_ratio + get_turbo_ratio( x ) ;
(...)
Je suis d'accord, mais cela peut rendre le .h compliqué dans mon cas
(voir plus bas).
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
Jusqu'à maintenant je faisais un sed -i "s///" sur le fichier
parameters.h.
J'ai recensé (j'aurais peut-être dû le faire dès le début) les
endroits où les constantes préprocesseur interviennent:
1///////// Prototypes de fonction. Effectivement ce n'est pas très
lisible ;-)
D'après ce que vous m'avez tous indiqué, je vois trois solutions:
- passer tous les paramètres, et s'occuper d'un plus ou moins grand
nombre de ceux-ci dans la fonction (il va quand même falloir regarder
à l'intérieur dans quel cas on est pour appliquer telle ou telle
instruction).
- faire plusieurs programmes pour autant de véhicule avec une fonction
f_graph_return différente à chaque fois (dur pour la maintenance si un
changement général dans f_graph_solve apparaissait);
- définir le prototype avec une macro préprocesseur dans le .c,
celle-ci étant définie dans le .h (juste pour la lisibilité, mais il
reste à rendre aussi lisible le corps de la fonction).
static void f_graph_return(struct graph gr
,struct results * res
,struct transmission trans
#if !defined(ELECTRIC_GENERATOR)
,struct internal_combustion_engine ice
#endif /* !defined(ELECTRIC_GENERATOR) */
2////////// Dans le corps des fonctions.
Voici deux exemples extraits de la fonction évoquée précédemment. J'ai
enlevé les commentaires (qui sont en assez grande quantité...).
Pas évident de mettre cela dans le .h, surtout que si je dois faire
comme ça à chaque fois, le .h risque de devenir gros ;-)
-------- 1er extrait
#if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING))
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0)
&& ABOUT_EQUAL_2(initial_acc_p_elec,0) )
{
it2max=1;
}
#else
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0) )
{
it2max=1;
}
#endif /* if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING)) */
---------- fin du premier extrait.
---------- 2ième extrait
#ifdef STOP_POSSIBILITY
int it;
for(it=0;it<10;it++)
{
printf("nItération %i.n",it);
#endif /* ifdef STOP_POSSIBILITY */
--------- fin du 2ième extrait
(le for est refermé plus loin).
Alors pour la libération, on pourrait peut-être imaginer initialiser
les pointeurs à NULL (actuellement j'ai une fonction d'allocation qui
réserve la mémoire, et par exemple pour un vecteur de réels, les
initialise à 0.0/0.0, i.e. NAN). Si le pointeur est resté à NULL,
c'est qu'il n'a pas été initialisé, on ne le libère pas. Ainsi on
pourrait libérer systématiquement tous les pointeurs dans une fonction
par structure. Est-ce une bonne solution?
En revanche pour l'allocation, soit on garde les constantes
préprocesseur, soit on utilise un enumération, mais ça revient à peu
près au même je trouve, sauf que avec les enum, il va falloir que le
type de véhicule soit passé en ligne de commande du programme (car je
ne vais pas le changer en dur dans les source .c ou .h à chaque fois
que je change de véhicule, et recompiler ensuite, autant utiliser une
constante préprocesseur à ce compte-là).
A moins d'avoir un projet trivial (on écrit, on utilise et on jette
dans la même matinée (mais dans ce cas C est généralement un mauvais
choix)), il est très rare que l'on perde du temps à réflèchir à ce
qu'on va faire.
Tu veux dire que la plupart du temps, sur les gros projets, les
programmeurs commencent à coder tout de suite?
Tous ces tests sur le véhicule sont-ils dans des endroits du
programme où la question de performance est importante (dans des
boucles fortement imbriquées) ?
Pas forcément. La réponse est plutôt non.
[...]ratio = x->motor_ratio + get_turbo_ratio( x ) ;
(...)
Je suis d'accord, mais cela peut rendre le .h compliqué dans mon cas
(voir plus bas).
Cela peut être entré de la ligne de commande par l'option '-D'
Oui, je suis bien sous GNU/Linux ;-) Merci pour l'info concernant gcc.
Jusqu'à maintenant je faisais un sed -i "s///" sur le fichier
parameters.h.
J'ai recensé (j'aurais peut-être dû le faire dès le début) les
endroits où les constantes préprocesseur interviennent:
1///////// Prototypes de fonction. Effectivement ce n'est pas très
lisible ;-)
D'après ce que vous m'avez tous indiqué, je vois trois solutions:
- passer tous les paramètres, et s'occuper d'un plus ou moins grand
nombre de ceux-ci dans la fonction (il va quand même falloir regarder
à l'intérieur dans quel cas on est pour appliquer telle ou telle
instruction).
- faire plusieurs programmes pour autant de véhicule avec une fonction
f_graph_return différente à chaque fois (dur pour la maintenance si un
changement général dans f_graph_solve apparaissait);
- définir le prototype avec une macro préprocesseur dans le .c,
celle-ci étant définie dans le .h (juste pour la lisibilité, mais il
reste à rendre aussi lisible le corps de la fonction).
static void f_graph_return(struct graph gr
,struct results * res
,struct transmission trans
#if !defined(ELECTRIC_GENERATOR)
,struct internal_combustion_engine ice
#endif /* !defined(ELECTRIC_GENERATOR) */
2////////// Dans le corps des fonctions.
Voici deux exemples extraits de la fonction évoquée précédemment. J'ai
enlevé les commentaires (qui sont en assez grande quantité...).
Pas évident de mettre cela dans le .h, surtout que si je dois faire
comme ça à chaque fois, le .h risque de devenir gros ;-)
-------- 1er extrait
#if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING))
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0)
&& ABOUT_EQUAL_2(initial_acc_p_elec,0) )
{
it2max=1;
}
#else
if ( ABOUT_EQUAL_2(initial_acc_p_meca,0) )
{
it2max=1;
}
#endif /* if (defined(ICE_ALONE) && defined(STOP_DO_NOTHING)) */
---------- fin du premier extrait.
---------- 2ième extrait
#ifdef STOP_POSSIBILITY
int it;
for(it=0;it<10;it++)
{
printf("nItération %i.n",it);
#endif /* ifdef STOP_POSSIBILITY */
--------- fin du 2ième extrait
(le for est refermé plus loin).
Alors pour la libération, on pourrait peut-être imaginer initialiser
les pointeurs à NULL (actuellement j'ai une fonction d'allocation qui
réserve la mémoire, et par exemple pour un vecteur de réels, les
initialise à 0.0/0.0, i.e. NAN). Si le pointeur est resté à NULL,
c'est qu'il n'a pas été initialisé, on ne le libère pas. Ainsi on
pourrait libérer systématiquement tous les pointeurs dans une fonction
par structure. Est-ce une bonne solution?
En revanche pour l'allocation, soit on garde les constantes
préprocesseur, soit on utilise un enumération, mais ça revient à peu
près au même je trouve, sauf que avec les enum, il va falloir que le
type de véhicule soit passé en ligne de commande du programme (car je
ne vais pas le changer en dur dans les source .c ou .h à chaque fois
que je change de véhicule, et recompiler ensuite, autant utiliser une
constante préprocesseur à ce compte-là).
Mais à mon humble avis, la tâche n'est pas facile, car le programme
est assez complexe d'un point de vue algorithmique, et du fait de la
multiplicité des cas de figure (les véhicules).
Le résultat a été à la hauteur des espérances
(plein de résultats très intéressants en des temps décents), mais il
est vrai que faudrait remettre tout ça à plat, pour la forme et
l'évolutivité du code.
Il faudrait une refonte qui prendrait à mon avis au moins un mois à
100%. Comme ce programme est réservé à un usage en interne et que mon
chef demande mille choses à la fois, avec le moins de temps passé à
programmer possible: "faut aller au plus vite", vue des choses que je
ne partage pas (d'où ce post), cela ne se fera pas d'ici un bon bout
de temps.
Mais à mon humble avis, la tâche n'est pas facile, car le programme
est assez complexe d'un point de vue algorithmique, et du fait de la
multiplicité des cas de figure (les véhicules).
Le résultat a été à la hauteur des espérances
(plein de résultats très intéressants en des temps décents), mais il
est vrai que faudrait remettre tout ça à plat, pour la forme et
l'évolutivité du code.
Il faudrait une refonte qui prendrait à mon avis au moins un mois à
100%. Comme ce programme est réservé à un usage en interne et que mon
chef demande mille choses à la fois, avec le moins de temps passé à
programmer possible: "faut aller au plus vite", vue des choses que je
ne partage pas (d'où ce post), cela ne se fera pas d'ici un bon bout
de temps.
Mais à mon humble avis, la tâche n'est pas facile, car le programme
est assez complexe d'un point de vue algorithmique, et du fait de la
multiplicité des cas de figure (les véhicules).
Le résultat a été à la hauteur des espérances
(plein de résultats très intéressants en des temps décents), mais il
est vrai que faudrait remettre tout ça à plat, pour la forme et
l'évolutivité du code.
Il faudrait une refonte qui prendrait à mon avis au moins un mois à
100%. Comme ce programme est réservé à un usage en interne et que mon
chef demande mille choses à la fois, avec le moins de temps passé à
programmer possible: "faut aller au plus vite", vue des choses que je
ne partage pas (d'où ce post), cela ne se fera pas d'ici un bon bout
de temps.