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 :

Des bonnes pratiques et toujours des questions


Sujet :

C

  1. #21
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    Bonsoir,
    Citation Envoyé par grim7reaper Voir le message
    En pratique (en C donc) ça ne le fait pas aussi bien que la version avec XOR : si tu échanges des entiers signés et que tu fais un overflow, paf ! Comportement indéterminé.
    En XOR, pas d’overflow possible.
    Quelque chose qui m'échappe.
    Comment le comportement est-il différent avec un signed ou unsigned?
    Quelle version XOR?

    Comment transcrire arithmétiquement la logique: ((a + b) - b) == ((a - b) + b)?

    J'ai beau imaginé les différents cas qui me viennent à l'esprit sur l'exploitation des 2 expressions, je n'arrive pas à trouver le cas où j'aurais droit à un paf, sans que ça ne soit le cas pour l'autre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            #define invert_1(x,y) x ^= y, y ^= x, x ^= y
     
            #define invert_2(a,b) (b = (a-b), a = (a-b), b = (b+a))
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  2. #22
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Bonsoir,

    Quelque chose qui m'échappe.
    Comment le comportement est-il différent avec un signed ou unsigned?
    Il n'a pas dit que le comportement était différent avec un signed d'un unsigned. il a juste donné l'exemple d'un signed pour dire que l'addition de deux nombres dont le résultat dépasse la capacité max d'un signed donnait un comportement indéterminé (pour moi ça coupait plutôt les bits qui dépassent ce qui est parfaitement déterminé mais je ne suis pas sûr de moi donc j'ai pas répondu)...

    Citation Envoyé par NVCfrm Voir le message
    Quelle version XOR?
    Il n'a pas parlé d'une version XOR particulière mais de la version du code utilisant XOR...

    Citation Envoyé par NVCfrm Voir le message
    J'ai beau imaginé les différents cas qui me viennent à l'esprit sur l'exploitation des 2 expressions, je n'arrive pas à trouver le cas où j'aurais droit à un paf, sans que ça ne soit le cas pour l'autre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
            #define invert_1(x,y) x ^= y, y ^= x, x ^= y
     
            #define invert_2(a,b) (b = (a-b), a = (a-b), b = (b+a))
    Moi non plus car comme la perte de "ce qui dépasse" donne des calculs cycliques (par exemple sur un signed char alors 127 + 1 = -128 et -128 - 1 = 127) on retombe toujours sur nos pattes.

    En plus, je serais curieux de voir si le codage très spécifique d'un float (avec mantisse et exposant) permet d'utiliser le XOR pour les permuter...
    Mon Tutoriel sur la programmation «Python»
    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
    Et on poste ses codes entre balises [code] et [/code]

  3. #23
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Bonsoir,

    Quelque chose qui m'échappe.
    Comment le comportement est-il différent avec un signed ou unsigned?
    L’overflow sur les entiers non signés est défini (quasi-sûr, mais à vérifier). Celui sur les entiers signés ne l’est pas (ça j’en suis sûr).

    La version XOR fait des manipulations bits à bits, pas de problème.
    La version arithmétique fait des additions (risque d’overflow) et des soustractions, problème.
    Citation Envoyé par NVCfrm Voir le message
    Quelle version XOR?
    À propos du swap de deux variables.

    Soit 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
    32
    33
    34
    35
    #include <stdio.h>
    #include <limits.h>
     
    void xor_swap(int* x, int* y);
    void add_swap(int* x, int* y);
     
    int main(void)
    {
        int a = INT_MAX;
        int b = 1;
        printf("bef: %d %d\n", a, b);
        xor_swap(&a, &b);
        printf("aft: %d %d\n", a, b);
        return 0;
    }
     
    void xor_swap(int* x, int* y)
    {
        if (x != y)
        {
            *x ^= *y;
            *y ^= *x;
            *x ^= *y;
        }
    }
     
    void add_swap(int* x, int* y)
    {
        if (x != y)
        {
            *x = *x + *y;
            *y = *x - *y;
            *x = *x - *y;
        }
    }
    En utilisant une option fort sympathique de clang, c’est très facilement visible.
    Avec le xor_swap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    % clang -fsanitize=undefined -o swap swap.c
    % ./swap
    bef: 2147483647 1
    aft: 1 2147483647
    Et si on remplace le xor_swap par un add_swap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    % clang -fsanitize=undefined -o swap swap.c
    % ./swap
    bef: 2147483647 1
    swap.c:32:17: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
    swap.c:33:17: runtime error: signed integer overflow: -2147483648 - 1 cannot be represented in type 'int'
    swap.c:34:17: runtime error: signed integer overflow: -2147483648 - 2147483647 cannot be represented in type 'int'
    aft: 1 2147483647

    Citation Envoyé par Sve@r Voir le message
    Il n'a pas dit que le comportement était différent avec un signed d'un unsigned. il a juste donné l'exemple d'un signed pour dire que l'addition de deux nombres dont le résultat dépasse la capacité max d'un signed donnait un comportement indéterminé (pour moi ça coupait plutôt les bits qui dépassent ce qui est parfaitement déterminé mais je ne suis pas sûr de moi donc j'ai pas répondu)...
    C’est ce que la plupart des compilateurs font (sauf en mode optimisations, on peut avoir des surprises). Mais la norme dit bien que c’est comportement indéterminé.

    Citation Envoyé par Sve@r Voir le message
    Moi non plus car comme la perte de "ce qui dépasse" donne des calculs cycliques (par exemple sur un signed char alors 127 + 1 = -128 et -128 - 1 = 127) on retombe toujours sur nos pattes.
    La norme n’impose pas l’usage du complément à 2. Même si en pratique, on trouve rarement autre chose de nos jours.

    Citation Envoyé par Sve@r Voir le message
    En plus, je serais curieux de voir si le codage très spécifique d'un float (avec mantisse et exposant) permet d'utiliser le XOR pour les permuter...
    L’opérateur ^ ne s’applique pas sur les nombres flottants donc c’est vite vu.
    Cela dit, en castant comme un bourrin en type entier suffisament large ça passera et tes deux nombres flottants seront bien échangé.
    Ça bosse bit à bit, donc ça fonctionne aussi bien pour un int que pour un float ou ce que tu veux. Comme memcpy qui copie (de façon bête et méchante) tout ce que tu veux.

  4. #24
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    Bonsoir grim7reaper

    Je ne connais pas cette option. Est ce que tu as essayé un underflow pour les 2 cas?
    Si je comprends bien, cela s'expliquerait par les différences des 2 opérations?
    Si je suis toujours ,l'addition nécessite un registre supplémentaire à la différence du xor. Comme l'a déjà fait remarquer un intervenant le xor a l'avantage d'épargner un registre.
    L'explication ne se trouve-t-elle pas là? Pas de résultat à lire pour scruter le bit d'overflow?
    Cela ne fait-il pas que le xor natif peut être une faille potentielle d'écriture en mémoire non?
    Je m'y perds un petit peu.
    Merci de vos lumières.
    Par contre:
    Citation Envoyé par grim7reaper Voir le message
    L’overflow
    ...
    Ça bosse bit à bit, donc ça fonctionne aussi bien pour un int que pour un float ou ce que tu veux. ...
    pour une addition ou soustraction ?
    Sinon l'avantage du xor est incontestable dans bien de cas n'est pas en cause. Les opérations arithmétiques étant construites par une surcharge de xor.
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  5. #25
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Citation Envoyé par NVCfrm
    Est ce que tu as essayé un underflow pour les 2 cas?
    Non, j’ai juste essayé un overflow dans les deux cas.
    Le fait est que c’est défini pour les unsigned :
    Citation Envoyé par ISO/IEC 9899:TC3, 6.2.5/9, page 34
    A computation involving unsigned operands can never overflow,
    because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
    mais pas pour les signed.
    Citation Envoyé par ISO/IEC 9899:TC3, 3.4.3, page 4
    An example of undefined behavior is the behavior on integer overflow.
    Je pense que ça vient du fait que en unsigned y’a pas 42 façons de gérer le trucs. Alors qu’en signed, ça va dépendre de comment tu les représentes.
    Et comme le C n’impose pas de représentation :
    Citation Envoyé par ISO/IEC 9899:TC3, 6.2.6.2/2, page 39
    If the sign bit is one, the value shall be modified in one of the following ways:
    — the corresponding value with sign bit 0 is negated (sign and magnitude);
    — the sign bit has the value −(2 N ) (two’s complement);
    — the sign bit has the value −(2 N − 1) (ones’ complement ).
    Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value.
    Je pense que la différence vient de là.

    Citation Envoyé par NVCfrm
    Si je comprends bien, cela s'expliquerait par les différences des 2 opérations?
    Oui.
    Le XOR est une opération logique.
    L’addition et la soustraction sont des opérations arithmétiques.

    Citation Envoyé par NVCfrm
    Si je suis toujours ,l'addition nécessite un registre supplémentaire à la différence du xor. Comme l'a déjà fait remarquer un intervenant le xor a l'avantage d'épargner un registre.
    L'explication ne se trouve-t-elle pas là? Pas de résultat à lire pour scruter le bit d'overflow?
    Pas vraiment de rapport avec le nombre de registres utilisés.
    C’est seulement que le concept d’overflow n’a aucun sens pour une opération logique.
    Le XOR il bosse bit à bit et il se base sur une table de vérité.
    Il prend un nombre A à N bits, un nombre B à N bit et il va produire un nombre C à N bits.

    Par contre une opération arithmétique peut faire un overflow car le résultat peut nécessiter un nombre de bits plus grand que celui des opérandes.

    Citation Envoyé par NVCfrm
    Cela ne fait-il pas que le xor natif peut être une faille potentielle d'écriture en mémoire non?
    C’est-à-dire ?

    Citation Envoyé par NVCfrm
    Par contre:
    Citation Envoyé par grim7reaper
    Ça bosse bit à bit, donc ça fonctionne aussi bien pour un int que pour un float ou ce que tu veux. ...
    pour une addition ou soustraction ?
    Ni l’une ni l’autre. Je parlais seulement du swap.

  6. #26
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    bonjour,
    merci pour ces explications fort utiles.
    Je suis encore toujours sur ma soif de détails plus ou moins obscurs, ou du besoin de discernement assez clair des nuances sur l'organisation des différences des opérations.

    Je commences à comprendre mieux certaines de tes remarques.

    Bosser bit à bit de façon logique implique 2 entrées et une sortie dirigée vers l'une des entrées.
    Supposons 'a' une entrée comportant une plage de 4 bits en entrée et 'b' faisant 3 bits qui est la deuxième entrée.
    Pour tout bit de 'a' ou 'b' aux positions correspondantes un xor pour basculer les bits de l'un sur l'autre. Est ce exact?

    Par exemple:
          | 1 | 0 | 1 | 0 |
       xor  
              | 1 | 0 | 1 |
         ___________________
        = | 1 | 1 | 1 | 1 |
    Cette opération en fonction du sens d'écriture du résultat s'écrira dans 'a' ou 'b'.
    15 et 7 en décimale pour l'un et l'autre.
    Donc le résultat est logiquement promu en 4 bits.
    Dans le cas de 2 objets de 4 bits faisant 15 et 1 en nombre décimaux, ou passera le bit supplémentaire du résultat?
    Comment se déroulera la logique avec le bit manquant ou en excès selon les cas?
    Et en arithmétique?
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

  7. #27
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par NVCfrm Voir le message
    Bosser bit à bit de façon logique implique 2 entrées et une sortie dirigée vers l'une des entrées.
    Supposons 'a' une entrée comportant une plage de 4 bits en entrée et 'b' faisant 3 bits qui est la deuxième entrée.
    Pour tout bit de 'a' ou 'b' aux positions correspondantes un xor pour basculer les bits de l'un sur l'autre. Est ce exact?

    Par exemple:
    | 1 | 0 | 1 | 0 |
    xor
    | 1 | 0 | 1 |
    ___________________
    =| 1 | 1 | 1 | 1 |
    C'est exact (mais l'affichage le rend mal).
    • 1 xor 1 = 0
    • 0 xor 0 = 0
    • 1 xor 0 = 0 xor 1 = 1

    En fait, le xor est une conjugaison de "et", de "non" et de "ou"
    a xor b = (a et non(b)) ou (non(a) et b)

    Citation Envoyé par NVCfrm Voir le message
    Cette opération en fonction du sens d'écriture du résultat s'écrira dans 'a' ou 'b'.
    15 et 7 en décimale pour l'un et l'autre.
    Donc le résultat est logiquement promu en 4 bits.
    Il est promu dans l'opérande le plus large utilisé (donc ici 4 bits).

    Citation Envoyé par NVCfrm Voir le message
    Dans le cas de 2 objets de 4 bits faisant 15 et 1 en nombre décimaux, ou passera le bit supplémentaire du résultat?
    Pourquoi "bit supplémentaire" ??? Même si parfois un xor ressemble à une addition ce n'en est pas une. 15 (1111) xor 1 (0001) donnera 1110 soit 14 (toujours sur 4 bits)

    Citation Envoyé par NVCfrm Voir le message
    Et en arithmétique?
    Je vais parler de "and" et de "or" pour essayer de clarifier mon texte (quand je dirai "et" ce sera alors la conjonction de coordination et non l'opérateur booléen).

    Donc on associe généralement "and" à la multiplication. Et "or" à l'addition. Parce que si on remplace "and" et "or" par une multiplication ou une addition, le résultat reste identique à celui des tables de Boole (1 * 0 = (1 and 0) = 0; 1*1 = (1 and 1) = 1; 0+0 = (0 or 0) = 0 et 0+1 = (0 or 1) = 1).
    Pour le "non" c'est un peu plus subtil. non(0) = 1 et non(1)=0. On peut alors le traduire par non(x)=1-x => (1-1 = 0 et 1-0=1).

    Si on applique alors ces équivalences au xor (qui est, rappelons-le, un compactage de "et", de "ou" et de "non", alors cela donnerait
    a xor b = (a and non(b)) or (non(a) and b)
    Traduisons cela en algèbre classique
    • 0 xor 0 = (0 * (1-0)) + ((1-0) * 0) = 0
    • 0 xor 1 = (0 * (1-1)) + ((1-0) * 1) = 1
    • 1 xor 0 = (1 * (1-0)) + ((1-1) * 0) = 1
    • 1 xor 1 = (1 * (1-1)) + ((1*1) * 1) = 0

    Donc le résultat algébrique correspond au résultat booléen... mais à condition qu'on reste en binaire. Parce que 15 xor 14 reste intraduisible algébriquement en calcul décimal...
    Mon Tutoriel sur la programmation «Python»
    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
    Et on poste ses codes entre balises [code] et [/code]

  8. #28
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 620
    Points
    23 620
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    C'est exact (mais l'affichage le rend mal).
    Corrigé avec les balises PRE.

  9. #29
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Cette histoire de promotion sur 4 bits ou sur le type de l'opérande de type "le plus grand" ne reflète pas la conception du C. Par exemple, même si a et b sont tous deux des (unsigned) char, le résultat de a^b ne sera pas un (unsigned) char à cause de la promotion des 'petits' entiers.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  10. #30
    Membre chevronné
    Avatar de NVCfrm
    Homme Profil pro
    Administrateur Système/Réseaux - Developpeur - Consultant
    Inscrit en
    Décembre 2012
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Administrateur Système/Réseaux - Developpeur - Consultant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2012
    Messages : 1 036
    Points : 1 917
    Points
    1 917
    Billets dans le blog
    5
    Par défaut
    Bonsoir Sve@r,

    Citation Envoyé par Sve@r
    Donc le résultat algébrique correspond au résultat booléen... mais à condition qu'on reste en binaire. Parce que 15 xor 14 reste intraduisible algébriquement en calcul décimal...
    Cette dernière remarque a été pour moi un éclair!
    L'exemple 15 xor 14 est le cas qu'il me fallait pour mieux cerner la logique xor. C'est l'illustration des propos de grim7reaper.

    Bonsoir diogene
    C'est un honneur de lire tes remarques sur les petites lacunes intrigantes de ces derniers échanges.
    Merci à tous.
    Ousmane


    Quand on tombe dans l'eau, la pluie ne fait plus peur.

Discussions similaires

  1. au sujet de l'intérêt des bonnes pratiques
    Par Invité dans le forum Débuter
    Réponses: 49
    Dernier message: 01/06/2009, 17h50
  2. [Procédures stockées] Bonnes pratiques de gestion des erreurs
    Par jbrasselet dans le forum Développement
    Réponses: 4
    Dernier message: 04/02/2009, 00h14
  3. Réponses: 3
    Dernier message: 29/12/2008, 16h31
  4. question a propos des bonnes pratiques ACCESS
    Par amne26 dans le forum IHM
    Réponses: 1
    Dernier message: 25/09/2008, 18h52
  5. [XML] Synthèse des bonnes pratiques XML
    Par neuromencien dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 21/03/2007, 21h55

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