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 :

Pointeur à false.


Sujet :

C++

  1. #1
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut Pointeur à false.
    Me v'là avoir perdu 5 bonnes minutes à cause d'une bête erreur. Quelqu'un pourrait m'expliquer pourquoi ni gcc ni VisualExpress ne râle avec une ligne comme ça:
    Oui, oui. Et après cela, p vaut bien NULL!

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Visual Studio 2005 ne râle pas non plus (avec warning level 4)

    Peut être parce que false vaut 0 et que c'est autorisé de mettre 0 dans un pointeur.

    Par contre, le code suivant provoque un warning "impossible de convertir de '' en 'void *'"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    enum { val_0, val_1 };
     
    int main(void)
    {
       void *p;
       p = val_0;
       return 0;
    }
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

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

    Informations professionnelles :
    Activité : aucun

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

    Simplement, parce que, la seule chose dont on soit sur, c'est que false vaut 0, alors que true vaut... tout le reste (même si la norme refuse que l'on puisse envisager d'incrémenter true ).

    A coté de cela, il se fait que NULL correspond à une adresse invalide, et, elle aussi, vaut 0 (0x00000000)...

    En effet, la plupart des implémentation de NULL sont de l'ordre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define NULL ((void*) 0)
    La preuve en est que tu peux tester ton pointeur directement sous la forme de
    if(ptr) pour t'assurer qu'il a été initialisé ou de if(!ptr) pour t'assurer qu'il n'existe pas

    Dés lors, que tu utilise false, 0 ou NULL pour t'assurer qu'un pointeur est invalide reviendra toujours au même

    Il est à noter que la nouvelle norme va introduire le terme null_ptr, qui sera plus explicite quant à la représentation, mais qui risque quand meme de n'etre, à l'implémentation que quelque chose comme...
    (à confirmer )
    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

  4. #4
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Oui je suis tout à fait d'accord mais alors pourquoi mon exemple avec une enum et val_0 (qui vaut 0, j'en suis sûr, j'ai regardé au debugger) provoque t'il un warning à la compilation.

    Cela veut t'il dire que le type boolean n'est pas un type mais un espece de nombre puisque'on peut faire "void *p = false" mais pas "void *p = val_0"
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Le type booléen est malheureusement lui aussi un #define de l'ordre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define false 0
    #define true !false
    (ou quelque chose dans le genre)

    Alors que l'énumération correspond à un TAD, au même titre qu'une structure, une union ou une classe.

    Il peut donc y avoir une vérification de type sur une énumération qu'il ne peut pas y avoir avec un booléen

    C'est la raison pour laquelle il est généralement recommandé d'utiliser les énumérations en lieu et place d'une série de #define "concurrents": Avec les #define, il ne peut y avoir aucune vérification quant à cohérence de la valeur utilisée, alors que, dans le cas des énumérations, les valeur sont regroupées... au sein du type dans lequel elles sont énumérées, ce qui permet au compilateur:
    • de vérifier si la valeur est du type attendu
    • de vérifier, dans le cas d'un test à choix multiple ("switch... case" ) de s'assurer que toutes les valeurs seront envisagées
    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

  6. #6
    Membre chevronné

    Inscrit en
    Octobre 2007
    Messages
    234
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 234
    Par défaut
    Les enum et les int ne sont pas convertibles implicitement en void*, ni les bool d'ailleurs (en tout cas gcc sort des erreurs), il faut croire que false (le littéral) lui a le droit d'être convertit en void*, true ne le peut pas.

    Je sais pas si le coup du false est défini dans la norme ou si c'est juste les compilos qui sont permissifs.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    En fait, ce que la norme dit, c'est:

    • les litéraux booléens sont les mots clé true et false
    • ces litéraux ont le type bool
    • Ce ne sont pas des lvalue
    • ils participe au processus de promotion des types entiers
    • les conversions en booléen sont implicites, et interviennent au même niveau que les conversion numériques (promotions d'entier ou de réels, conversion d'entier, de réels en entiers, de pointeurs et de pointeurs sur membres)
    • une rvalue arithmétique, une énumération, un pointeur et un pointeur sur membre peuvent être convertie en rvalue de type bool. Une valeur nulle, un pointeur à valeur nulle, ou un pointeur sur membre à valeur nulle sera converti à false; tout autre valeur sera convertie à true
    • une rvalue de type bool peut etre convertie en entier, false devenant 0 et true devenant 1
    • surement encore d'autres choses intéressantes...

    Ce qu'il ressort de tout cela, c'est que, au final tout peut être converti en booléen selon le principe 0 ==> false !0==>true et un booleen peut être converti en n'importe quoi selon le principe false ==>0 true ==>1

    NULL étant le transtypage "barbare" de 0 en un pointeur de type void, mais un pointeur n'étant jamais qu'un entier (soit unsigned int soit unsigned long), et les entiers étant implicitement convertibles en booléen, mais un booléen intervenant dans l'ordre des promotions d'entiers (bool->char->short->int->long), l'initialisation d'un pointeur à false correspond exactement à l'initialisation à NULL...

    Comme indiqué, du fait qu'une énumération représente un type abstrait de donnée, le C++ est capable de vérifier si le type correspond à ce qui est attendu, ce qui justifie que, de son coté, l'utilisation d'une valeur énumérée valant 0 ne pourra être envisagée que si elle est transtypée en pointeur du type correspondant
    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

  8. #8
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Il est à noter que la nouvelle norme va introduire le terme null_ptr, qui sera plus explicite quant à la représentation, mais qui risque quand meme de n'etre, à l'implémentation que quelque chose comme...
    (à confirmer )
    Euh, non, quand même pas… sinon quel serait l'intérêt de ce nouveau mot-clé ?!
    http://www.open-std.org/jtc1/sc22/wg...2007/n2431.pdf
    Il s'agit de nullptr, et non null_ptr
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  9. #9
    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
    Je me suis embêté à faire un billet dessus
    http://blog.developpez.com/alp?title..._le_pointeur_n

    Bonne lecture

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    D'après ton article, nullptr est une valeur d'un nouveau type std::nullptr_t.
    Ça me rappelle beaucoup la manip artisanale que j'avais faite...
    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.

  11. #11
    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
    Citation Envoyé par Médinoc Voir le message
    D'après ton article, NULL est une valeur d'un nouveau type std::nullptr_t.
    Ça me rappelle beaucoup la manip artisanale que j'avais faite...
    Non, c'est nullptr qui est un objet de type nullptr_t

    C'est précisément ce qui est dit dans la norme.
    C'est un peu le même principe que ta manip artisanale

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Que false soit converti en 0 et le pointeur se retrouve à NULL, c'est bien le comportement attendu. Ce qui me gène c'est de ne pas avoir eu au - un warning m'indiquant la conversion implicite.
    Par exemple, quand je fais :, j'ai bien un warning. Et même pire, si je fais , j'ai carrément une erreur. Ce que je comprends.
    Du coup, j'ai perdu un peu de temps à voir pourquoi mon booléen dans ma structure ne changeait pas de valeur avant de me rendre compte que j'avais écrit trop vite...

  13. #13
    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
    Tu peux toujours utiliser le "nullptr trick".

    Tu définis les conversions implicites qui te conviennent et c'est réglé.

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Me v'là avoir perdu 5 bonnes minutes à cause d'une bête erreur. Quelqu'un pourrait m'expliquer pourquoi ni gcc ni VisualExpress ne râle avec une ligne comme ça:
    Oui, oui. Et après cela, p vaut bien NULL!
    false est une constante entière de valeur nulle. Toute constante entière de valeur nulle peut être utilisée comme pointeur nul.

    Citation Envoyé par koala01 Voir le message
    En effet, la plupart des implémentation de NULL sont de l'ordre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define NULL ((void*) 0)
    Aucune implémentation conforme du C++ peut avoir une telle définition de NULL (elle est autorisée pour le C).

    En passant, le fait que NULL soit une constante entière de valeur nulle (en C++, en C on peut aussi avoir une telle valeur castée en void*) n'indique rien du tout sur sa représentation.

    La preuve en est que tu peux tester ton pointeur directement sous la forme de
    if(ptr) pour t'assurer qu'il a été initialisé ou de if(!ptr) pour t'assurer qu'il n'existe pas
    J'ai du mal à voir en quoi c'est la preuve de quoi que ce soit.

    Citation Envoyé par koala01 Voir le message
    Le type booléen est malheureusement lui aussi un #define de l'ordre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #define false 0
    #define true !false
    (ou quelque chose dans le genre)
    bool est un type de base en C++ et true et false des mots clés. Pas des define ni des typedefs.

    NULL étant le transtypage "barbare" de 0 en un pointeur de type void,
    Non -- a plus d'un titre. Premièrement en C++ NULL ne peut pas être (void*)0. Deuxièmement, le (void*) n'a pas pour but d'être un transtypage barbare (que je comprends comme un reinterpret_cast<>). Le cast en question ici serait un static_cast en C++. L'objectif de ce cast est de passer un void* dans des contextes comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void f(int, ...);
    ...
    f(1, NULL);
    ...
    où une définition de NULL comme 0 passerait simplement un entier. La différence étant justement visible sur les architectures où (void*) 0 et 0 ne partage pas la même représentation (la différence la plus commune,mais pas la seule, étant une taille différente)

    mais un pointeur n'étant jamais qu'un entier (soit unsigned int soit unsigned long),
    Depuis quand?

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    false est une constante entière de valeur nulle. Toute constante entière de valeur nulle peut être utilisée comme pointeur nul.
    Doit-on comprendre que ces valeurs ne sont pas fortement typés (l'expression n'est pas correcte, mais j'en trouve pas de meilleure): toutes les constantes entières de valeur nulle suivantes: 0, false et NULL sont équivalentes et peuvent donc être utilisées dans les types suivants sans qu'il y ait un avertissement de transtypage: bool, pointeur, scalaire?
    Effectivement, aucun warning (Visual Express) pour le code suivant:
    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
       int i1=false;
       int i2=NULL;
       int i3=0;
     
       bool b1=0;
       bool b2=NULL;
       bool b3=false;
     
       A*p1=0;
       A*p2=false;
       A*p3=NULL;
     
       char c1=NULL;
       char c2=0;
       char c3=false;
     
       short s1=NULL;
       short s2=0;
       short s3=false;
     
       long l1=NULL;
       long l2=0;
       long l3=false;
     
       float f1=NULL;
       float f2=0;
       float f3=false;
     
       double d1=NULL;
       double d2=0;
       double d3=false;
    gcc me sort un warning pour chaque conversion de NULL vers un scalaire (int, bool, char, short, long, float, double).

  16. #16
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Doit-on comprendre que ces valeurs ne sont pas fortement typés (l'expression n'est pas correcte, mais j'en trouve pas de meilleure): toutes les constantes entières de valeur nulle suivantes: 0, false et NULL sont équivalentes et peuvent donc être utilisées dans les types suivants sans qu'il y ait un avertissement de transtypage: bool, pointeur, scalaire?
    C'est simplement une valeur qui est surchargee (de meme que null en Ada ou nil en Pascal).

    Le compilateur peut avertir pour ce qu'il veut -- voir gcc pour NULL, on pourrait imaginer la meme chose pour false. Techniquement, la norme ne demande pas de diagnostique pour cela.

    Note que (36L+3*2-42) est aussi une constante entiere de valeur nulle. (0L a ete utilise comme definition de NULL sur des archi ou long avait la meme taille qu'un pointeur alors qui int etait plus petit pour le meme genre de raisons qui ont pousse a utiliser (void*)0).

Discussions similaires

  1. pointeurs
    Par ghost74 dans le forum C
    Réponses: 3
    Dernier message: 14/12/2002, 02h52
  2. Pointeur vers un tableau
    Par Nikos dans le forum C
    Réponses: 3
    Dernier message: 09/12/2002, 00h43
  3. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  4. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  5. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44

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