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
    Expert éminent sénior
    Signification d'un double point d'interrogation
    Bonjour,

    à ce jour, en C comme dans un tas d'autres langages, je connaissais ! que je traduis par "inverse ce qui suit".

    Mais aujourd'hui, dans le code source de pulseaudio12.2, je rencontre
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
                    conf->system_instance = !!b;

    Sachant que conf->system_instance est un bool et b un int, je me (vous !) demande tout simplement pourquoi ne pas avoir écrit
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    conf->system_instance = b;


    Merci de vos (comme d'habitude ) lumineuses explications, et bon 14 juillet !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  2. #2
    Expert éminent
    J'ai regardé sur Internet, et la réponse est dans la question

    En C, toute valeur différente de 0 est true. Avec la double négation logique, on uniformise en réduisant aux valeurs 1 ou 0.
    • 0, false - !!0 vaut 0
    • n’importe quelle autre valeur, true - !!X vaut 1


    Il y a surtout plusieurs manières de faire ... + ou - portable, mais effectivement 1 test ternaire me semble plus propre ((X != 0)? 1: 0).

  3. #3
    Expert éminent sénior
    Pas trouvé sur le web (faut dire aussi que rechercher langage C explication "!!" ne m'a pas remonté des merveilles, fallait pas rêver).

    Merci pour ta réponse, cependant tu ne réponds pas à ma question : pourquoi ne pas avoir utilisé tout simplement conf->system_instance = b; puisque si b vaut 0 le boolean sera false, sinon il sera true.
    Et c'est exactement ce que tu écris.

    Je ne vois pas ce que
    Citation Envoyé par foetus Voir le message
    on uniformise en réduisant aux valeurs 1 ou 0.
    apporte.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  4. #4
    Expert éminent
    Citation Envoyé par Jipété Voir le message
    Pas trouvé sur le web (faut dire aussi que rechercher langage C explication "!!" ne m'a pas remonté des merveilles, fallait pas rêver).
    Il faut chercher "C double not logical"


    Citation Envoyé par Jipété Voir le message
    pourquoi ne pas avoir utilisé tout simplement conf->system_instance = b; puisque si b vaut 0 le boolean sera false, sinon il sera true.
    pour cela il faut lire le code, et voir comment cette variable conf->system_instance est utilisée.
    Mais on peut penser que conf veut dire configuration, et que dans 1 fichier de configuration ou 1 de base données, c'est plus facile d'avoir 2 valeurs 0 et 1 (les tests, le parsage des valeurs, l'écriture, ...) que 58446591 pour true

  5. #5
    Rédacteur/Modérateur

    C'est une vieille syntaxe qui rapporte !b sur [0,1] puis prend l'inverse. Qui permet d'avoir 1 si b != 0, 0 sinon.
    Une syntaxe récente sera juste conf->system_instance = b != 0;
    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.

  6. #6
    Expert éminent
    Citation Envoyé par Bousk Voir le message
    Une syntaxe récente sera juste conf->system_instance = b != 0;
    Non la + récente est 1 cast conf->system_instance = (_Bool) b;.

    Édit : Et même ici le cast ne sert à rien parce qu'on travaille en C et il faut que la variable conf->system_instance soit de type _Bool.
    Donc la solution la + récente mais effectivement, il faut utiliser le nouveau type C99 dans son code ... ce qui ne semble pas être le cas

  7. #7
    Expert éminent sénior
    Citation Envoyé par foetus Voir le message
    pour cela il faut lire le code, et voir comment cette variable conf->system_instance est utilisée.:
    Y aura pas des millions de possibilités, hein :
    Citation Envoyé par Jipété Voir le message
    Sachant que conf->system_instance est un bool
    (conf c'est la structure des options de configuration, oui)


    Citation Envoyé par foetus Voir le message
    Il faut chercher "C double not logical"
    Fallait en avoir l'idée ! Bien joué !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  8. #8
    Expert éminent sénior
    Bonjour
    Citation Envoyé par Jipété Voir le message
    Y aura pas des millions de possibilités, hein :
    Hé non. Et j'ai beau chercher, je ne vois pas non plus l'avantage à forcer "b" à être 1 plutôt que 572542. Même la brillante () suggestion de foetus à propos des bdd ne me convainc pas (l'insertion d'un int dans un bool provoquera un cast implicite dans le champ de la bdd) ; et dans le code C lui-même, partout où b sera utilisé comme un booléen, alors sa valeur réelle n'a pas d'importance (sauf si évidemment on vient tester explicitement if (conf->system_instance == 1) mais je ne pense pas qu'un professionnel C fasse cette monumentale bêtise).
    Toutefois admettons que pour une obscure raison cela soit nécessaire, alors comme foetus j'aurais préféré le ternaire bien détaillé => conf->system_instance=b ?1 :0. Là avec son !!b je pense que l'auteur de pulseaudio12 a voulu écrire un truc à la "one again" mais qui ne séduit en fait personne.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  9. #9
    Responsable 2D/3D/Jeux

    Bonjour,

    Je pense que cela devient nécessaire lorsque vous ne savez pas exactement si le type pour représenter un booléen sera équivalent au int. En effet, dans un logiciel multi-plateforme, dont les plateformes cibles sont très variées, le type pour les booléens peut être un int, comme il peut être totalement différent sur une autre plateforme.
    La solution par le cast explicite de foetus est équivalente, mais pas nécessairement jolie (car le cast, peut être considéré comme le mal ?).

    Ensuite, j'ai testé sur godbolt.org, la sortie ASM. Mon code :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef int bool;
    int myConf = 42;
    bool b = 4242;
     
    int foo() {
        myConf = !!b;
        //myConf = (bool) b;
    }

    La version avec le cast, c'est deux mov :
    Code asm :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
            mov     eax, DWORD PTR b[rip]
            mov     DWORD PTR myConf[rip], eax


    La version avec la double négation :
    Code asm :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
            mov     eax, DWORD PTR b[rip]
            test    eax, eax
            setne   al
            movzx   eax, al
            mov     DWORD PTR myConf[rip], eax
            nop


    Donc, mouais ...
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  10. #10
    Expert confirmé
    @LittleWhite, je ne comprends pas le lien entre ce que tu écris et l'exemple que tu donnes.
    Ton exemple montre que si le type bool n'est pas le _Bool du langage C, le fait de faire un cast ne donne pas le résultat attendu, et donc que l'utilisation du double '!' est plus sure.
    Il a totale équivalence, et ces trois expressions aurons le même code assembleur :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    _Bool x1 = (b != 0);
    _Bool x2 = !!b;
    _Bool x3 = (_Bool)b;
    Si par contre on a un type bool qui n'a donc pas la conversion implicite : tout nombre converti en bool devient 1 s'il est non nul et 0 sinon. Et dans cas, la troisième ligne est à éviter. Personnellement j'utilise la première forme, mais j'aime bien la seconde.

  11. #11
    Expert éminent
    Citation Envoyé par Jipété Voir le message
    Y aura pas des millions de possibilités
    Si il y a 1 différence entre la notion booléenne mathématique (2 valeurs, vrai ou faux) et la notion C (parce qu'il n'y a pas de booléen, sauf à partir du C99 avec le type _Bool)

    Donc il y a 1 dichotomie entre les données en mémoire et celles externes dans 1 fichier ou 1 base de données, par exemple.
    Et pour des données externes, il faut faire en sorte que tes valeurs ont la notion que tout le monde attend (et non pas 1 valeur informatique de geek )


    Citation Envoyé par dalfab Voir le message
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    _Bool x1 = (b != 0);
    _Bool x2 = !!b;
    _Bool x3 = (_Bool)b;
    Ton code montre que le cast n'est pas nécessaire ... parce qu'on est en C
    Si j'ai mis le cast c'est parce qu'on ne connait pas les types de conf->system_instance et de b (<- en réalité, mon commentaire est mauvais parce qu'il faut utiliser ce type dans son code)


    Si par contre on a un type bool qui n'a donc pas la conversion implicite
    En C99, le type booléen existe _Bool Et dans l'entête stdbool.h tu as des alias : bool, false et true.
    Je ne travaille pas avec mais je m'attends qu'il fasse les conversions implicite vers les valeurs 0 et 1.


    tout nombre converti en bool devient 1 s'il est non nul et 0 sinon. Et dans cas, la troisième ligne est à éviter.
    Explique pourquoi C'est ce qu'on recherche, non ?

  12. #12
    Expert éminent
    Ce qui fausse le résultat de Littlewhite, c'est le :
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  13. #13
    Expert éminent sénior
    Citation Envoyé par foetus Voir le message
    Si j'ai mis le cast c'est parce qu'on ne connait pas les types de conf->system_instance et de b
    Mais si ! Et depuis le début, et c'est dans le code :

    Citation Envoyé par Jipété Voir le message
    Sachant que conf->system_instance est un bool et b un int,
    Plus précisément : system_instance est un membre (parmi plein d'autres) de type booléen niché au cœur de la structure conf.

    Vous allez me perdre, là, (smiley bateau_qui_coule -- on ne l'a pas, celui-là, )
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    Expert éminent sénior
    Citation Envoyé par Jipété Voir le message
    Vous allez me perdre, là,
    C'est parce qu'on est en train de discuter du sexe des anges. Tout le monde a son avis et les avis de chacun sont tous valables à cause de la permissivité du C concernant le booléen.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  15. #15
    Expert éminent sénior
    Citation Envoyé par Sve@r Voir le message
    C'est parce qu'on est en train de discuter du sexe des anges.


    M'en vais te leur soulever la jupe, moi, on va y voir plus clair :

    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
    #include <stdio.h>
     
    int main(int argc, char **argv)
    {
      _Bool systeminstance;
      int b;
     
      b = 0;
      systeminstance = b;
      printf("%d\n", systeminstance);
     
      b = 1;
      systeminstance = b;
      printf("%d\n", systeminstance);
     
      b = 9;
      systeminstance = b;
      printf("%d\n", systeminstance);
     
      systeminstance = !b;
      printf("%d\n", systeminstance);
     
      systeminstance = !!b;
      printf("%d\n", systeminstance);
     
    	return 0;
    }


    et on s'en doute, la console nous dit :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    # ./test 
    0
    1
    1
    0
    1
    #
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

###raw>template_hook.ano_emploi###