IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

alternative à l'opérateur ternaire ?


Sujet :

C

  1. #1
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut alternative à l'opérateur ternaire ?
    Bonjour,
    Dans mon programme j'ai implémenté la célèbre macro MAX qui retourne le maximum de deux nombres en utilisant l'opérateur ternaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Cette macro retourne la valeur maximale entre x et y */
    #define BLDONNEES_MAX(x, y) ((x)>(y)?(x):(y))
    Pour des raisons que je ne maîtrise pas, je n'ai pas le droit d'utiliser l'opérateur ternaire dans mon code... Hors j'appelle cette macro assez souvent....
    Il faut donc que je l'implémente différemment. Sachant que je m'en sers pour dimenssionner des tableaux, il faut qu'elle reste sous la forme de macro, donc pas d'implémentation par fonction.
    Comment faire ?

  2. #2
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Ca risque être très difficile, puisque l'opérateur ternaire effectue un remplacement d'expression (comme en caml), utiliser toute autre structure (un if par exemple), implique l'exécution d'une ou plusieurs instructions, par conséquent, la structure de ton programme devra être modifiée si tu désire utiliser une macro.

  3. #3
    Membre averti
    Avatar de Foobar1329
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 283
    Points : 387
    Points
    387
    Par défaut
    Hello,

    Citation Envoyé par tut
    Bonjour,
    Dans mon programme j'ai implémenté la célèbre macro MAX qui retourne le maximum de deux nombres en utilisant l'opérateur ternaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Cette macro retourne la valeur maximale entre x et y */
    #define BLDONNEES_MAX(x, y) ((x)>(y)?(x):(y))
    Pour des raisons que je ne maîtrise pas, je n'ai pas le droit d'utiliser l'opérateur ternaire dans mon code... Hors j'appelle cette macro assez souvent....
    Il faut donc que je l'implémente différemment. Sachant que je m'en sers pour dimenssionner des tableaux, il faut qu'elle reste sous la forme de macro, donc pas d'implémentation par fonction.
    Comment faire ?
    Hé bien tu peux mapper ta macro sur une fonction qui fait le boulot de renvoyer le max. Exple (j'ai mis des double pour pouvoir travailler avec un max de types basiques C, mais tu peux faire une fonction qui travaille avec simplement des int dans ton contexte) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    #include <stdio.h>
     
    /*
     My old macro
    #define  BLDONNEES_MAX(x,y) ((x)>(y)?(x):(y))
     */
     
    /* My new macro */
    #define  BLDONNEES_MAX(x,y) max_d((double)(x),(double)(y))
     
    double max_d(double a, double b) {
       double res = 0.0;
       if (a > b) {
          res = a;
       }
       else {
          res = b;
       }
       return res;
    }
     
    int main(void) {
     
       int a=1, b=3;
     
       printf("max=%d\n", (int) BLDONNEES_MAX(a,b));
     
       return 0;
     
    }
    A+

  4. #4
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Dans ce cas, alors pourquoi utiliser un macro ?

    De plus, pourquoi utilises tu une variable intermédiaire ?

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par tut
    Sachant que je m'en sers pour dimenssionner des tableaux, il faut qu'elle reste sous la forme de macro
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    effectivement,
    je m'en sers pour dimensioner des tableaux, donc pas de fonction.
    il faut que je trouve une autre version utilisant seulement de la macro-programmation...

  7. #7
    Membre averti

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Points : 422
    Points
    422
    Par défaut
    salut

    j'ai une première proposition:
    #define MAX(X,Y) (X + (X<Y)*(Y-X))

    et une deuxième (malheureusement celle ci est typée):

    int tab_max[2] = {0};
    #define MAX(X,Y) ((tab_max[1] = Y-X), X + tab_max[(X<Y)])

    ça pourrait aussi s'écrire comme ça:

    int tab_max[2];
    #define MAX(X,Y) (tab_max[0] = X, tab_max[1] = Y, tab_max[(X<Y)])

  8. #8
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 76
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Points : 1 913
    Points
    1 913
    Par défaut
    Dans ce cas, alors pourquoi utiliser un macro ?
    Peut être que dans ce cas l'appel est 'inline' (le code est substitué à l'appel).
    De plus, pourquoi utilises tu une variable intermédiaire ?
    Ca c'est sûr. Une initialisation et deux affectations pour rien.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  9. #9
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    Merci acx01b !!
    la première solution fonctionne impeccable, bravo, fallait la trouver !
    Tu m'enlèves une fière chandelle du pied !

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par PRomu@ld
    Ca risque être très difficile, puisque l'opérateur ternaire effectue un remplacement d'expression (comme en caml), utiliser toute autre structure (un if par exemple), implique l'exécution d'une ou plusieurs instructions, par conséquent, la structure de ton programme devra être modifiée si tu désire utiliser une macro.

    si si ça peut se faire... Pas clair, mais ça existe...

    Pour aujourdhui je suis pas sur l'ordi où j'ai ça mais je le mettrais ce soir ou cette nuit...

    Un define peut tout à fait être une fonction... Si je me souviens, faut jongler avec les accolades, les parenthèses, et les \ de continuation de ligne....
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #11
    Membre averti

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Points : 422
    Points
    422
    Par défaut
    celle ci me parait sympathique aussi, mais encore une fois elle est typée (ne marche que pour des entiers)

    #define MAX(X,Y) (X + ( (-(int)(X<Y)) & (Y-X) ) )

  12. #12
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    je te signale que pour que l'expression marche tout le temps, quelle que soit les varaibles, il suffit d'entourer chaque variable de parenthèses..

    (cela forme un peu l'équivalent de "void" : cela prendra n'importe quoi entier, reel, chaine de caractères, expression...).
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  13. #13
    Membre averti

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Points : 422
    Points
    422
    Par défaut
    voici un petit programme d'essai de vitesse de chacune des macros
    on voit que MAX1 <=> MAX2 <=> MAX5 en temps sur les entiers
    et que MAX3 et MAX4 ne sont pas bonnes

    par ailleurs toutes sont optimisees aussi bien sur les constantes avec l'option -O3

    et MAX5 a l'air d'être la meilleure sur les flottants

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    #include <time.h>
    #include <stdio.h>
     
    int tab_max3[2] = {0};
    int tab_max4[2];
    #define MAX1(X,Y) (X + ( (-(int)(X<Y)) & (Y-X) ) )
    #define MAX2(X,Y) (X + (X<Y)*(Y-X))
    #define MAX3(X,Y) (tab_max3[0] = X, tab_max3[1] = Y, tab_max3[(X<Y)])
    #define MAX4(X,Y) (tab_max4[1] = Y-X, X + tab_max4[(X<Y)])
    #define MAX5(X,Y) (X < Y ? Y : X)
     
    #define N 504500000
    int main() {
        int i,a,b,c,n;
        unsigned int k;
        for (n = 0; n < 10; n++) {
            k = clock();
            for (i = 0; i < N; i++) {
                a = MAX1(0,0);
                b = MAX1(-9,-5);
                c = MAX1(-400000,255);
            }
            printf("%d ",clock() - k);
     
            k = clock();
            for (i = 0; i < N; i++) {
                a = MAX2(0,0);
                b = MAX2(-9,-5);
                c = MAX2(-400000,255);
            }
            printf("%d ",clock() - k);
     
            k = clock();
            for (i = 0; i < N; i++) {
                a = MAX3(0,0);
                b = MAX3(-9,-5);
                c = MAX3(-400000,255);
            }
            printf("%d ",clock() - k);
     
            k = clock();
            for (i = 0; i < N; i++) {
                a = MAX4(0,0);
                b = MAX4(-9,-5);
                c = MAX4(-400000,255);
            }
            printf("%d ",clock() - k);
     
            k = clock();
            for (i = 0; i < N; i++) {
                a = MAX5(0,0);
                b = MAX5(-9,-5);
                c = MAX5(-400000,255);
            }
            printf("%d ",clock() - k);
            printf("\n");
        }
     
    }

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par acx01b
    salut

    j'ai une première proposition:
    #define MAX(X,Y) (X + (X<Y)*(Y-X))

    et une deuxième (malheureusement celle ci est typée):

    int tab_max[2] = {0};
    #define MAX(X,Y) ((tab_max[1] = Y-X), X + tab_max[(X<Y)])

    ça pourrait aussi s'écrire comme ça:

    int tab_max[2];
    #define MAX(X,Y) (tab_max[0] = X, tab_max[1] = Y, tab_max[(X<Y)])
    salut, en général, en math, on utilise la relation suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
              a+b+|a-b|
    max(a,b)=----------
                  2
     
             a+b-|a-b|
    min(a,b)=----------
                  2

  15. #15
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par PRomu@ld
    Ca risque être très difficile, puisque l'opérateur ternaire effectue un remplacement d'expression (comme en caml), utiliser toute autre structure (un if par exemple), implique l'exécution d'une ou plusieurs instructions, par conséquent, la structure de ton programme devra être modifiée si tu désire utiliser une macro.
    Comme je disais plus haut....


    ok j'ai fait un p'tit AR sur linux pour vous tirer les exemples...

    Comme vous verrez, à part 1 ou 2 trucs, c'est un ENFER de maintenance , MAIS on peut bien évidemment définir des fonctions....

    ça couvre pas mal tout (les constantes à part, voir ci-dessus).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    .....
    #define STRNEQ(a, b, n)	(strncmp((a),(b),(n))==0)
     
    .....
    #ifndef MAX
    #   define MAX(x, y) (((x)>(y)) ? (x) : (y))
    #endif
     
    ....
    #define NUM_ELEM(a)	(sizeof(a)/sizeof((a)[0]))
     
    ......
    /* Statements() macro - failsafe way to define multi-statement macros */
    #define Statements(a) do { a; } while(FALSE)
     
    ......
    #define CmnSwapBytes(a, b, c) CmnSwapBytes1((a), (b), (char *)(c))
     
    ......
    #define Debug(function)		function
     
    ......
    #define Debug_msg(function)\
        (void) fprintf(stderr,"%s\n",(function))
     
    #define Debug_fmt1(fmt, a) \
        fprintf(stderr, (fmt), (a))
     
    #define Debug_fmt2(fmt, a, b) \
        fprintf(stderr, (fmt), (a), (b))
     
    ......
    /* Appel d'une fonction avec champs pré-remplis */
    #define DmScenarioIdAddHoursToDate(id, v) \
        CmnAddHoursToDate(&((id).year),&((id).month),&((id).day),&((id).hour),(v));
     
    ......
    /* Calculs indirects */
    #define DmScenarioIdAddHoursToProg(id, v) \
        (id).prog += (v)
     
    ....... 
    extern void DmPopupDataPanel(void);
    #define DmPopupAndRaiseDataPanel()  DmPopupDataPanel()
     
    ......
    #define		RangeIntersects(a, b) \
        (((a)->max>(b)->max && (a)->min>=(b)->min) || \
         ((a)->max<=(b)->max && (a)->min<(b)->min))
     
    ......
    /* Remplacement d'alloc et de free !!!!!!!!! */
    typedef struct {
        double T, theta;
    } MPoint;
     
    #define MPointsNew(n) \
        (MPoint*)CmnMalloc((n)*sizeof(MPoint))
    #define MPointsDestroy(points) \
        free((points))
    ....
    Bref, on peut tout faire.... Y compris tout un tas de c.nneries..... pour rendre du code illisible , rien de mieux
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  16. #16
    Membre expérimenté
    Avatar de muad'dib
    Homme Profil pro
    Développeur Java
    Inscrit en
    Janvier 2003
    Messages
    1 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2003
    Messages : 1 011
    Points : 1 375
    Points
    1 375
    Par défaut
    Moi je me pose une question : quel est l'intérêt d'interdire l'utilisation de l'opérateur ternaire ? Même au niveau pédagogique je vois pas bien l'intérêt là...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 11/04/2006, 11h41
  2. opérateur ternaire
    Par the big ben 5 dans le forum Langage
    Réponses: 7
    Dernier message: 23/02/2006, 18h06
  3. Equivalant opérateur ternaire C++
    Par Pero dans le forum Langage
    Réponses: 5
    Dernier message: 07/10/2005, 09h44
  4. [java] pb Opérateur ternaire
    Par phileme dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 04/07/2004, 13h10
  5. Opérateur ternaire
    Par MASSAKA dans le forum Langage
    Réponses: 14
    Dernier message: 13/05/2004, 15h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo