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 :

"comparison between pointer and integer", un coup c'est oui, un coup c'est non..;


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juillet 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2018
    Messages : 27
    Par défaut "comparison between pointer and integer", un coup c'est oui, un coup c'est non..;
    Bonjour la communauté,

    Si je code ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    bool b;
    std::string route="010010";
    std::string rte="";
    for(int i(0); i<6; i++)
    {
    	rte=route[i];
    	if(rte=="0") b=false;
    	if(rte=="1") b=true;
    	// fait des trucs avec b
    }
    le compilateur (Mingw avec Code::Blocks) ne dit rien.

    Mais si je code ainsi (pour économiser la variable rte qui ne sert apparemment pas à grand chose) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    bool b;
    std::string route="010010";
     
    for(int i(0); i<6; i++)
    {
    	if(route[i]=="0") b=false;
    	if(route[i]=="1") b=true;
    	// fait des trucs avec b
    }
    le compilateur m'accuse de comparer des choses incomparables :

    warning: comparison with string literal results in unspecified behaviour [-Waddress]|
    error: ISO C++ forbids comparison between pointer and integer [-fpermissive]|

    Je ne comprends pas trop quelle est la différence entre ces 2 codes qui, dans mon esprit, devraient produire le même comportement, i.e. déterminer le booléen true ou false suivant que le charactère n°i de la chaîne route vaut "0" ou "1"...
    Où donc me plante-je ?

    Rick.

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 144
    Billets dans le blog
    4
    Par défaut
    std::string::operator[] retourne un char.
    " est le délimiteur de chaînes de caractères.
    ' est le délimiteur de caractère.
    Le premier code est très médiocre.
    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.

  3. #3
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juillet 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2018
    Messages : 27
    Par défaut
    Oki ; donc le "bon code" ce serait ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    bool b;
    std::string route="010010";
    for(int i(0); i<6; i++)
    {
    	if(route[i]=='0') b=false;
    	if(route[i]=='1') b=true;
    	// fait des trucs avec b
    }
    Question subsidiaire, quelle différence avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(route.at(i)=='0') b=false;
    if(route.at(i)=='1') b=true;
    Une question de goût ?
    Rick.

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

    Informations professionnelles :
    Activité : aucun

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

    A vrai dire, tu pourrais même simplifier encore le code, à partir du moment où tu as la certicude (qu'il te faudra acquérir ) que ta chaine de caractères ne contient que des "0" et des "1".

    Car, tant que tu as cette certitude (qui est facile à obtenir), tu peux partir du principe que "si on n'a pas un ''1'', c'est qu'on a un ''0'' ", si bien que le code "idéal" serait sans doute proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    for(size_t i = 0;i<route.size();++i){// size_t parce que les indice sont d'office non signés
                                         //route.size(), pour s'assurer que l'on n'essaye pas d'accéder à des caractères qui n'existent pas ;) 
        bool isOne{route[i]=='1'} ; // 1- on déclare les données au plus proche de leur utilisation réelle, et, autant que possible, en leur donnant tout de suite la valeur cohérente qui convient ;)
               // 2 - on donne, autant que faire se peut, un nom qui indique l'usage qui sera fait des fonctionnalités que l'on utilise
        if(isOne){
             /* que faire si on avait "1" */
        }else{
            /* que faire si on avait "0"
        }
    }
    Et, à partir de là, on peut même encore simplifier le code pour lui donner la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    or(size_t i = 0;i<route.size();++i){// size_t parce que les indice sont d'office non signés
                                         //route.size(), pour s'assurer que l'on n'essaye pas d'accéder à des caractères qui n'existent pas ;) 
     
        if(route[i]=='1'){
             /* que faire si on avait "1" */
        }else{
            /* que faire si on avait "0"
        }
    }
    Pour répondre à la question subsidiaire, les fonctions at() sont de pures aberrations qui n'auraient jamais du être insérée dans la bibliothèque standard

    Pour faire simple, elles traient une erreur de logique (le développeur essaye d'accéder à un élément qui n'existe pas), comme s'il s'agissait d'une situation à laquelle le développeur est dans l'incapacité d'échapper et dont il doit tenir compte "plus haut dans la pile d'appels" (en lançant une exception).

    Le pire étant que le test qu'elle effectuera pour s'assurer que cette erreur ne survient pas sera aussi effectué en production, alors que l'erreur aurait du être corrigée depuis longtemps

    Ce n'est donc pas juste "une question de goût" : c'est une réaction "viscérale", conceptuellement justifiée suite à une meilleur compréhension des enjeux que celle qui avait cours lors de la mise au point de la bibliothèque standard (qui date quand même des année '90)
    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

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 491
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    std::string::operator[] retourne un char. .
    Bien vu !

    Pour expliciter les conséquences :

    Code 1
    rte=route[i]; à droite, on a un caractère, à gauche une std::string et il existe un opérateur légal d'affectation (voir forme 4 https://fr.cppreference.com/w/cpp/st...ng/operator%3D)
    rte=route[i]if(rte=="0") on compare une std::string à un const char* et il existe un opérateur légal de comparaison (sans doute en construisant une std::string temporaire et en comparant ensuite les 2 std::strings)

    Code 2
    if(route[i]=="0") on compare un char (qui est un entier = integer en anglais) à un const char* (qui est un pointeur)
    // au final, on a donc bien une comparison between pointer and integer

  6. #6
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Juillet 2018
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2018
    Messages : 27
    Par défaut
    Merci à tous pour vos explications.

    Citation Envoyé par koala01 Voir le message
    (...) A vrai dire, tu pourrais même simplifier encore le code, à partir du moment où tu as la certicude (qu'il te faudra acquérir ) que ta chaine de caractères ne contient que des "0" et des "1". (...)
    => J'ai effectivement cette certitude, la chaîne est crée par un constructeur d'objet. ^^

    Citation Envoyé par koala01 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for(size_t i = 0;i<route.size();++i) // size_t parce que les indice sont d'office non signés
                                         //route.size(), pour s'assurer que l'on n'essaye pas d'accéder à des caractères qui n'existent pas ;)
    => Bien vu le "route.size()"

    Citation Envoyé par koala01 Voir le message
    // on déclare les données au plus proche de leur utilisation réelle, et, autant que possible, en leur donnant tout de suite la valeur cohérente qui convient
    Oui alors du coup je rebondis là dessus :

    la déclaration "au plus près" se fait dans ce cas au sein d'une boucle. Je me demande quel est le comportement :
    - la variable est redéclarée (un genre de var[i]) et le compilateur gère ça tout seul ? si oui ça peut ponctuellement générer de l'espace mémoire utilisé "pour rien" vu que var[i-1] ne sert plus à rien...
    - la variable est détruite à chaque itération lors de l'atteinte de "}" de la boucle et est re-crée lors de l'itération suivante ? Si oui alors c'est du temps de cycle en plus par rapport à une déclaration juste en amont de la boucle...
    c'est sans doute métaphysique comme question vu la puissance des machines mais comme je me la pose depuis un bon moment, s'il y a moyen d'avoir une réponse...

    Rick.

  7. #7
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 144
    Billets dans le blog
    4
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(size_t i = 0;i<route.size();++i){// size_t parce que les indice sont d'office non signés
                                         //route.size(), pour s'assurer que l'on n'essaye pas d'accéder à des caractères qui n'existent pas ;)
    Allons Koala, nous sommes en 2019 for (char c : route) est encore plus sûr.

    la déclaration "au plus près" se fait dans ce cas au sein d'une boucle. Je me demande quel est le comportement :
    - la variable est redéclarée (un genre de var[i]) et le compilateur gère ça tout seul ? si oui ça peut ponctuellement générer de l'espace mémoire utilisé "pour rien" vu que var[i-1] ne sert plus à rien...
    - la variable est détruite à chaque itération lors de l'atteinte de "}" de la boucle et est re-crée lors de l'itération suivante ? Si oui alors c'est du temps de cycle en plus par rapport à une déclaration juste en amont de la boucle...
    c'est sans doute métaphysique comme question vu la puissance des machines mais comme je me la pose depuis un bon moment, s'il y a moyen d'avoir une réponse...
    On s'en moque pas mal. Tu passes d'un code qui faisait des copie, création et comparaison de string à "oui mais le nombre de cycles cpu alors ?"
    Si tu te souciais vraiment des performances le premier code n'aurait jamais vu le jour. Et de toute façon non tu n'as pas besoin de courir après les performances à ce point.
    Une variable ça n'existe pas, c'est juste un artefact pratique à manipuler quand on écrit le code.
    Le compilateur il ne traite que des adresses, et il sera assez intelligent pour réserver la mémoire nécessaire, et l'optimiser au passage.
    char c; ne crée rien. Ça va à peine réserver une adresse dans la stack. Ça ne construit rien non plus, les variables de type primitif ne sont pas construites par défaut contrairement à une classe.
    C'est pour ça qu'une variable a une valeur aléatoire par défaut.
    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.

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 491
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Rick_Cplusplus Voir le message
    le compilateur gère ça tout seul ? si oui ça peut ponctuellement générer de l'espace mémoire utilisé "pour rien" vu que var[i-1] ne sert plus à rien...
    Si nous, pauvres petits développeurs, nous sommes posé cette question, alors il est évident que le compilateur aussi. Il est bien plus fort que nous pour optimiser du code alors laissons-le faire.

    Il y a une petite condition pour cela : écrire le code le plus simple possible. Eviter de faire des pseudo-optimisations en se disant "je vais orienter le compilateur". N'oublions pas que le compilateur est écrit par des humains pour reconnaître des patterns.......que des humains ont identifié. Si tu fais un code trop alambiqué, ton compilateur risque de se dire "mais qu'est ce que ça veut dire?... aucune idée, faisons une traduire naïve (ndlr : et donc peu optimisée)".

    Citation Envoyé par Bousk Voir le message
    Allons Koala, nous sommes en 2019 for (char c : route) est encore plus sûr.
    Et tellement plus clair

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

Discussions similaires

  1. Comparison between signed and unsigned integer expression
    Par darkwall_37 dans le forum Débuter
    Réponses: 4
    Dernier message: 27/03/2014, 16h17
  2. comparison between pointer and integer
    Par sculpteur dans le forum Objective-C
    Réponses: 1
    Dernier message: 03/12/2010, 17h31
  3. Réponses: 5
    Dernier message: 18/09/2009, 18h56
  4. Réponses: 12
    Dernier message: 22/12/2006, 00h00

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