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

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2023
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Avril 2023
    Messages : 1
    Points : 3
    Points
    3
    Par défaut C++17 crée une utilisation pratique de l'opérateur d'indexation de tableau rétrograde, par Raymond Chen
    C++17 crée une utilisation pratique de l'opérateur d'indexation de tableau rétrograde, par Raymond Chen, Senior Software Engineer chez Microsoft

    Il est bien connu que si a est un pointeur ou un tableau et i un entier, alors a[i] et i[a] sont équivalents en C et C++, ce qui donne lieu à des hilarités telles que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void haha()
    {
        int a[5];
        for (i = 0; i < 5; i++) {
            i[a] = 42;
        }
    }
    Il y a très peu d'utilisation pratique pour cette équivalence, à part pour faire des farces aux gens¹.

    Et puis C++17 est arrivé.

    L'un des changements apportés au langage de base en C++17 a été le renforcement de l'ordre des règles d'évaluation, formellement connu sous le nom de séquençage. Nous avions déjà rencontré ce problème en étudiant un crash qui semblait concerner une opération std::move.

    L'une des opérations qui a reçu un ordre d'évaluation défini est l'opérateur d'indice. À partir de C++17, a[b] évalue toujours a avant d'évaluer b.

    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
    int* p;
    int index();
     
    auto test()
    {
        return p[index()];
    }
     
    // Compiled as C++14
     
        sub     rsp, 40
        call    index       ; call index first
        movsxd  rcx, rax
        mov     rax, p      ; then fetch p
        mov     eax, [rax + rcx * 4]
        add     rsp, 40
        ret
     
    // Compiled as c++17
     
        push    rbx
        sub     rsp, 32
        mov     rbx, p      ; fetch p first
        call    index       ; then call index
        movsxd  rcx, rax
        mov     eax, [rbx + rcx * 4]
        add     rsp, 32
        pop     rbx
        ret
    Par conséquent, si votre évaluation de l'index peut avoir un effet secondaire sur l'évaluation du pointeur, vous pouvez inverser l'ordre pour forcer l'index à être calculé en premier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    auto test()
    {
        return index()[p];
    }
    Étonnez vos amis ! Déconcertez vos ennemis !

    Bavardage en prime : clang implémente cela correctement, mais msvc (v19) et gcc (v13) se trompent d'ordre et chargent p avant d'appeler index. (Par comparaison, icc se trompe aussi, mais dans l'autre sens : Il charge toujours p en dernier).

    ¹ Une autre utilisation pratique est de contourner toute surcharge possible de l'opérateur [], comme indiqué dans le chapitre 14 de Imperfect C++ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define ARRAYSIZE(a) (sizeof(a) / sizeof(0[a]))
    En inversant l'ordre dans 0[a], cela permet de contourner une éventuelle surcharge de a[].

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::vector<int> v(5);
    int size = ARRAYSIZE(v); // compiler error
    Cependant, cette méthode n'est pas infaillible. Il suffit de créer un imbécile plus astucieux : Si v est un pointeur ou un objet convertible en pointeur, alors ce pointeur ira volontiers à l'intérieur de 0[...].

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct Funny
    {
        operator int*() { return oops; }
        int oops[5];
        int extra;
    };
     
    Funny f;
    int size1 = ARRAYSIZE(f); // oops: 6
     
    int* p = f;
    int size2 = ARRAYSIZE(p); // oops: 1
    Heureusement, vous n'avez pas besoin d'astuces macro. Vous pouvez laisser les fonctions constexpr du C++ faire le travail à votre place :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<typename T, std::size_t N>
    constexpr std::size_t array_size(T(&)[N]) { return N; }

    Et vous ?

    Qu'en pensez-vous ?

    Voir aussi :

    Les travaux sur la norme C++ 23 sont terminés et cette nouvelle version porte le nom de code "Pandemic Edition", C++ 23 cherche à améliorer la vitesse de compilation et l'hygiène du code

    Zig, présenté comme une alternative moderne au C, fait son apparition dans le top 50 de l'indice Tiobe des langages les plus populaires. Carbon, l'alternative C++ de Google, n'est classé que 168e

    C++ vs Rust : une comparaison pratique de la vitesse de compilation et de test des deux langages de programmation, par Matthew Glazar, ingénieur en génie logiciel

  2. #2
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 227
    Points
    20 227
    Par défaut
    Qu'en pensez-vous ?
    Que c'est exactement ces trucs qui font que ca me manque pas du tout de plus faire de C++ dans mon nouveau job
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2019
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Septembre 2019
    Messages : 203
    Points : 988
    Points
    988
    Par défaut
    Je ne suis pas sûr de bien comprendre.

    Va être une écriture valide ? C'est pour faciliter la lisibilité du code, c'est ça ?

    Sinon, les décideurs derrière la norme C++ ne pourraient pas faire des trucs utiles pour la vie de tous les jours, pour faciliter l'écriture et la lisibilité ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 118
    Points : 32 984
    Points
    32 984
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Raymond Chen Voir le message
    Et vous ?

    Qu'en pensez-vous ?
    Gadget, et je vois pas comment quiconque de sencé pourrait écrire un tel code ou le laisser passer en revue.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Citation Envoyé par grunk Voir le message
    Que c'est exactement ces trucs qui font que ca me manque pas du tout de plus faire de C++ dans mon nouveau job
    +1
    Il est bien connu que si a est un pointeur ou un tableau et i un entier, alors a[i] et i[a] sont équivalents en C et C++
    Alors ça, je ne savais pas ! depuis quand ?

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 635
    Points : 10 568
    Points
    10 568
    Par défaut
    Citation Envoyé par jmv Voir le message
    Alors ça, je ne savais pas ! depuis quand ?
    Effectivement c'est la question depuis quand ?

    Mais je pense que c'est 1 peu 1 fausse question
    C'est plus le compilateur qui convertit a[i] en *(a + i) … et donc c'est interchangeable *(i + a).
    Après il faudrait 1 expert gcc/ LLVM pour me dire si j'ai tord

  7. #7
    jmv
    jmv est déconnecté
    Membre confirmé Avatar de jmv
    Profil pro
    Enseignant
    Inscrit en
    Mai 2004
    Messages
    395
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Mai 2004
    Messages : 395
    Points : 603
    Points
    603
    Par défaut
    Effectivement, ça parait logique.
    Donc la réponse à ma question initiale serait : depuis qu'il existe un compilateur C.

  8. #8
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 568
    Points : 7 670
    Points
    7 670
    Par défaut
    L'équivalence a[i] === *(a+i) === i[a] est la base du C, existe donc depuis le début.
    Il existe un petit écart en C++, le résultat de a[i] est une x-value au lieu d'une l-value si l'expression a n'est pas une l-value, donc a[i] n'est pas totalement équivalent à i[a].

    Ce qui change c'est que désormais l'ordre d'exécution est garanti, du moins depuis le C++17, je ne sais pas pour le C.
    Donc pour fct1()[ fct2() ], on sait quelle fonction est appelée en premier, c'est fct1(). Mais par exemple pour fct1() = fct2();, on commence par fct2(). Ça me parait complexe de se souvenir de ça!

    De plus, cette "astuce" me parait doublement contreproductive en C++, pour 2 raisons:
    - on ne devrait pas utiliser l'arithmétique des pointeurs en C++. Il est préférable d'utiliser les objets faits pour cela.
    - si on veut une chronologie précise. Il est bien plus lisible et sûr de décomposer l'expression:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    auto&&  x = fct1();
    auto&&  y = fct2();  // ou dans l'ordre inverse
    auto  z = x[ y ];
    Les analyseurs de code doivent systématiquement tagger une ligne auto z = fct(1)[ fct2() ] comme étant dangereuse.

Discussions similaires

  1. Utilisation pratique d'une douchette QR code
    Par symfonyc dans le forum Général Conception Web
    Réponses: 1
    Dernier message: 17/05/2017, 16h45
  2. Est-ce une bonne pratique d'utiliser les DELETE CASCADE ?
    Par Tanebisse dans le forum Développement
    Réponses: 21
    Dernier message: 14/10/2016, 13h20
  3. [Swing] Utiliser du HTML: Une bonne pratique ?
    Par dranzul dans le forum AWT/Swing
    Réponses: 6
    Dernier message: 28/07/2011, 09h42
  4. Quel CMS pour une utilisation personnelle ?
    Par lennelei dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 30/08/2009, 11h21
  5. Quels SGBD sont gratuits pour une utilisation commerciale ?
    Par laffreuxthomas dans le forum Décisions SGBD
    Réponses: 28
    Dernier message: 15/03/2005, 16h51

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