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 :

[gcc] opérateur conditionnel ternaire "?:"


Sujet :

C++

  1. #1
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut [gcc] opérateur conditionnel ternaire "?:"
    encore bonjour,

    est ce que vous savez comment gcc compile l'opérateur ( bool ? true : false ) ??

    est ce que c'est simplement l'équivalent d'un if avec affection d'une variable temporaire, ou est ce qu'il y a des optimisations de faites ?

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Oui, comme tous les compilateurs C++, et C aussi d'ailleurs.
    Pour ce qui est de l'optimisation, elle n'est pas différente de n'importe quelle formule mathématique.

  3. #3
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Citation Envoyé par zais_ethael
    Oui, comme tous les compilateurs C++, et C aussi d'ailleurs.
    Pour ce qui est de l'optimisation, elle n'est pas différente de n'importe quelle formule mathématique.
    est ce que tu peut clarifier ta réponse stp...

    "Oui" à quelle question

    et de quelle formule mathématique parles tu? on parle bien d'un "if" la, n'est ce pas ?

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    est ce que vous savez comment gcc compile l'opérateur ( bool ? true : false ) ??
    Il se démerde, c'est son problème.

    est ce que c'est simplement l'équivalent d'un if avec affection d'une variable temporaire, ou est ce qu'il y a des optimisations de faites ?
    Question performances, c'est kif-kif, le choix se fait plutôt sur la solution qui est la plus lisible, la plus facile à écrire, la plus maintenable., et ça, ça dépend du contexte.

  5. #5
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Citation Envoyé par Sylvain Togni
    Question performances, c'est kif-kif, le choix se fait plutôt sur la solution qui est la plus lisible, la plus facile à écrire, la plus maintenable., et ça, ça dépend du contexte.
    Merci c'est ce que j'avais besoin de savoir, mais sur quoi tu te base pour affirmer cela ?

    Citation Envoyé par Sylvain Togni
    Il se démerde, c'est son problème.
    Quand on sait pas, on se tait ^^

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Quand on sait pas, on se tait ^^
    En plusieurs années de programmation je n'ai jamais eu à me poser cette question. Et quand bien même je voudrais le savoir, j'examinerais le code source ASM produit par le compilateur. De toute façon le résultat dépendra du contexte : dans certains cas le compilo pourra optimiser, dans d'autres non.

  7. #7
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Citation Envoyé par Laurent Gomila
    En plusieurs années de programmation je n'ai jamais eu à me poser cette question. Et quand bien même je voudrais le savoir, j'examinerais le code source ASM produit par le compilateur. De toute façon le résultat dépendra du contexte : dans certains cas le compilo pourra optimiser, dans d'autres non.
    Il est temps de clore le sujet alors si personne ne veut connaitre la réponse (sauf moi on dirait..)

  8. #8
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Salut,

    En fait, il faut bien retenir qu'un code fonctionnel est beaucoup plus souvent lu qu'il n'est écrit.

    Le premier rôle d'un code source est donc d'être facilement compris par la personne qui l'a entre les mains

    L'opérateur ternaire ? est, certes, intéressant pour l'écriture du code, mais selon sa position dans le reste du code, selon ce qu'il fait dans les deux cas, selon son rôle, il a le très gros défaut de... rendre le code plus compliqué à lire.

    Dans certains cas, ce n'est pas "catastrophique":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void fonct(int i)
    {
        cout<<"salut "
            <<(i>3 ? "la populace" :"tout le monde")
            <<endl;
    }
    ne posera que peu de problème à la lecture, mais, dans d'autres cas il y a clairement moyen de faire quelque chose d'incompréhensible
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void fonct(int i)
    {
        cout<<"salut "
            <<(i==0 ? "toi":(i>3 ? "la populace":"tout le monde"));
    }
    devient déjà bien moins évident à comprendre, bien que ce soit un code parfaitement valide.

    Dans le premier cas, quand dans trois mois tu reverra le code, tu le comprendra *relativement* facilement, alors que dans le deuxième cas, il te faudra quand même quelques secondes de réflexion pour savoir ce que tu a voulu écrire

    C'est tout simplement là dessus que l'on se base pour dire que la facilité d'écriture, d'entretien et de lecture dépend fortement du contexte dans lequel tu utilise l'opérateur ternaire

    Pour ce qui est de la manière dont le compilateur va le gérer n'intéresse... que le compilateur et ceux qui créent le compilateur... Ce qu'on demande, c'est qu'il puisse le gérer correctement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Merci pour cette réponse claire (la seule de ce post), qui vient confirmer mon opinion de ne pas utiliser cet opérateur trop souvent.

    Cependant ma réponse reste, car ce qui m'est venu à l'esprit en premier lieu, c'est : est ce qu'il aurait une différence de performance entre ces deux manières d'écrire ?

    Je ne comprends le refus général qu'il y a au fait de savoir s'il on peut utiliser cet instructions pour optimiser certains endroits du code.

  10. #10
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Non, en général la seule optimisation permise par cet opérateur est une optimisation de lignes de code. Une fois compilé (et hors optimisations), il y aura quoiqu'il arrive un test et un saut.
    C'est une opération assez basique, il n'y a pas 50 manières de la coder en langage machine.

  11. #11
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    ok merci. Je m'en doutais un peu, je voulais juste une petite confirmation, rien de plus

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Pour préciser un peu ce qu'a écrit Laurent...

    Il faut bien te dire que le rôle du compilateur est... de transformer quelque chose qui est lisible par l'humain ... en quelque chose qui est utilisable par le processeur...

    Pour que le processeur puisse effectuer un test, il ne dispose que d'une liste bien précise d'instructions (cmp, jmp, jne, je et quelques autres)

    A partir du moment ou un branchement doit être fait de manière conditionnelle, on "retombera" systématiquement sur l'une ou l'autre des instructions de cette liste
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Citation Envoyé par mamelouk
    Merci pour cette réponse claire (la seule de ce post), qui vient confirmer mon opinion de ne pas utiliser cet opérateur trop souvent.

    Cependant ma réponse reste, car ce qui m'est venu à l'esprit en premier lieu, c'est : est ce qu'il aurait une différence de performance entre ces deux manières d'écrire ?

    Je ne comprends le refus général qu'il y a au fait de savoir s'il on peut utiliser cet instructions pour optimiser certains endroits du code.
    Pourtant, c'est clairement indiqué plus haut, ça ne change rien à par la lisibilité.
    Ce qui veut dire qu'il y a beaucoup de réponses plus que pertinentes sur ce topic, et en revanche une question qui montre clairement que tu n'as pas correctement lu ton cours/livre sur le C++.

  14. #14
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Si je fais remonter ce thread, c'est pour une dernière précision:

    dans 90 à 95 % des cas, l'opérateur ternaire pourra être joyeusement remplacé par un if else (ou un switch), ne serait-ce que pour une question de facilité de relecture (étant entendu que, si gain il y a, il ne sera clairement pas significatif )

    Par contre, il reste les 5 à 10 derniers % des cas dans lesquels leur utilisation est, pour le moins, justifiée - à défaut de pouvoir assurer qu'elle est incontournable (si l'un des "pontes" pouvait confirmer ou infirmer ).

    Ainsi, je m'intéresse pour l'instant à la bibliothèque loki, qui travaille énormément avec les template.

    Dans cette bibliothèque, on rencontre entre autre une classe template qui se présente, entre autre, sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct IndexOf<TypeList<head, tail>, T>
    {
        private:
            enum {temp=IndexOf<taile, T>::value};
        public:
            enum (value= temp == -1  ? -1 : 1+temp);
    };
    Je ne suis franchement pas persuadé qu'il y ai moyen d'obtenir le même résultat avec une structure if else correspondant à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    enum
    { 
        if(temp==-1)
            value=-1;
        else 
            value=1 + temp;
    };
    Encore une fois, il s'agit donc de bien se rendre compte du fait que, certaines techniques peuvent s'avérer être "peu recommandable" pour une majorité des cas, mais tout à fait justifiées (voire, être la seule solution) pour des cas particuliers.

    Et je peux t'assurer que l'opérateur ternaire est loin d'être le seul exemple de ce fait
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Comme les valeurs sont connues à la compilation lorsque l'on manipule les typelists de loki, on arrive à déterminer la valeur à la compilation. Impossible avec un branchement if/else.

    En effet, l'opérateur ternaire est pas mal utilisé dans la métaprogrammation.

    Il fait partie du bagage dont on dispose pour "métaprogrammer".

    ( ps : ah ça y est tu t'y mets )

  16. #16
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par Alp Voir le message
    ( ps : ah ça y est tu t'y mets )
    Ca fait quelque temps que je m'y intéresse, mais, par manque de temps, principalement, je fais cela par étape
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  17. #17
    screetch
    Invité(e)
    Par défaut
    salut,

    il y a des optis realisees par le compilauteur parfois
    le code siuivant est compilé sans saut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int i = (test > 0) ? 2 : 3;
    mais le if qui fait la meme chose aussi.



    je ne suis pas d'accord avec ce que vous dites, la principale difference entre if et ?: c'est que ?: renvoie une valeur et pas if. Donc quand j'ecris la ligne plus haut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    i = (test > 0) ? 2 : 3;
    ca me parait plus clair que le if.

    La raison c'est que si je cherche ou est initialisé i je tombe sur un seul endroit, alors qu'avec le if c'est a deux endroits. Si l'expression elle meme me parait moins lisible, je m'en fiche, car quand je cherche un bug, je n'ai pas besoin de comprendre tous le code que je vois; je fais confiance pour que la fonction size() renvoie une taille sans aller verifier le code; je suis sur que i est un compteur de boucle ou une variable temporaire de peu d'interet; je cherche un bug qui a deja un diagnostique.

    Le fait de couper une initialisation de variable en 2 ou d'imbriquer des IF complexifie ma recherche.

    Sauf dans le cas d'utilisation "trop" complexes (trop imbriquees, expressions trop longue).

    Il est possible d'ecrire du ternaire lisible aussi, quand les gens montrent des exemples de ternaire ils montrent toujours des exemples ou les gens mettent meme pas d'espace, mais rien n'interdit le ternaire d'etre ecrit sur plusieurs lignes aussi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = (test > 0) ?
               2
             : 3

  18. #18
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    Citation Envoyé par Miles Voir le message
    Pourtant, c'est clairement indiqué plus haut, ça ne change rien à par la lisibilité.
    Ce qui veut dire qu'il y a beaucoup de réponses plus que pertinentes sur ce topic, et en revanche une question qui montre clairement que tu n'as pas correctement lu ton cours/livre sur le C++.
    Avec toutes les réponses intéressantes qu'on donné les autres, tout ce que trouve faire un responsable de developpez.com, c'est de troller... bravo

  19. #19
    Membre émérite
    Avatar de mamelouk
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    867
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2005
    Messages : 867
    Par défaut
    merci screetch pour cette clarification.

    on m'avais expliqué que le ++i était plus rapide que le i++, du fait que i++ retourne la valeur avant l'incrémentation et est donc obligé de la stocker.

    en comparaison, si l'opérateur ?: renvoie une valeur (pour l'affectation) alors que lors de l'utilisation d'un if, l'affectation est faite sans qu'il ait de "return", est ce que cela ne signifie pas qu'un simple if-else est plus rapide ?

    j'imagine que le compilateur n'est pas stupide au point de générer une fontion avec "return", mais encore fois ceci n'est qu'une discussion.. Si vous etes trop intelligents pour ne pas supporter mes questions allez troller ailleurs...

  20. #20
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Citation Envoyé par mamelouk Voir le message
    on m'avais expliqué que le ++i était plus rapide que le i++, du fait que i++ retourne la valeur avant l'incrémentation et est donc obligé de la stocker.
    C'est valable pour les itérateurs complexes comme les std::vector<>::iterator. Pour les entiers simples, le compilateur optimise sans problème puisque le retour n'est pas utilisé et qu'il connaît parfaitement le fonctionnement des entiers (contrairement aux types plus complexes)
    Citation Envoyé par mamelouk Voir le message
    en comparaison, si l'opérateur ?: renvoie une valeur (pour l'affectation) alors que lors de l'utilisation d'un if, l'affectation est faite sans qu'il ait de "return", est ce que cela ne signifie pas qu'un simple if-else est plus rapide ?
    On peut dire que l'opérateur ?: peut être en partie être traité par la partie statique du compilateur (celle qui gère les template), ce qui n'est pas le cas d'un if. Dans le cas dynamique (le test n'est pas fixé à la compilation), le code est sans num doute écrit avec deux affectations et il est équivalent à un if simple.
    Citation Envoyé par mamelouk Voir le message
    j'imagine que le compilateur n'est pas stupide au point de générer une fontion avec "return", mais encore fois ceci n'est qu'une discussion..
    Le compilateur ne génèrera pas de fonction pour ça. Si tu ne lui dis pas de créer une fonction, elle ne sera pas créée, jamais.
    Citation Envoyé par mamelouk Voir le message
    Si vous etes trop intelligents pour ne pas supporter mes questions allez troller ailleurs...
    No comment.

Discussions similaires

  1. opérateur if ternaire
    Par Kindersurpriz dans le forum Débuter
    Réponses: 17
    Dernier message: 07/08/2008, 20h04
  2. surcharge d'opérateur if ternaire
    Par elmcherqui dans le forum C++
    Réponses: 5
    Dernier message: 18/06/2008, 20h44

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