Qu’est-ce que (x ^ 0x1)! = 0 signifie?

Je suis tombé sur l’extrait de code suivant

if( 0 != ( x ^ 0x1 ) ) encode( x, m ); 

Que signifie x ^ 0x1 ? Est-ce une technique standard?

    L’opération XOR ( x ^ 0x1 ) inverse le bit 0. L’expression signifie donc effectivement: si le bit 0 de x est égal à 0 ou si tout autre bit de x vaut 1, l’expression est vraie.

    A l’inverse, l’expression est fausse si x == 1.

    Donc, le test est le même que:

     if (x != 1) 

    et est donc (sans doute) inutilement obscurci.

    • ^ est l’opération XOR au niveau du bit
    • 0x1 est 1 en notation hexadécimale
    • x ^ 0x1 inversera le dernier bit de x (référez-vous à la table de vérité XOR dans le lien ci-dessus si ce n’est pas clair pour vous).

    Donc, la condition (0 != ( x ^ 0x1 )) sera vraie si x est supérieur à 1 ou si le dernier bit de x est 0. Ce qui ne laisse que x == 1 comme valeur à laquelle la condition sera fausse . Donc c’est équivalent à

     if (x != 1) 

    PS Enfer d’une façon de mettre en œuvre une condition aussi simple, je pourrais append. Ne fais pas ça. Et si vous devez écrire un code compliqué, laissez un commentaire . Je t’en supplie.

    Cela peut sembler être une explication simplifiée, mais si quelqu’un veut le parcourir lentement, c’est ci-dessous:

    ^ est un opérateur XOR au niveau du bit dans c, c ++ et c #.

    Un XOR au niveau du bit prend deux types de bits de même longueur et effectue l’opération OU exclusif logique sur chaque paire de bits correspondants.

    L’OR exclusif est une opération logique qui affiche true lorsque les deux entrées diffèrent (l’une est vraie, l’autre est fausse).

    La table de vérité d’ un xor b :

     aba xor b ---------------------------- 1 1 0 1 0 1 0 1 1 0 0 0 

    0 == ( x ^ 0x1 ) expression 0 == ( x ^ 0x1 ) au niveau binary:

      what? xxxxxxxx (8 bits) xor 00000001 (hex 0x1 or 0x01, decimal 1) gives 00000000 --------------------------- the only answer is 00000001 

    alors:

      0 == ( x ^ 0x1 ) => x == 1 0 != ( x ^ 0x1 ) => x != 1 

    C’est un opérateur exclusif OR (XOR). Pour comprendre comment cela fonctionne, vous pouvez exécuter ce code simple

      std::cout << "0x0 ^ 0x0 = " << ( 0x0 ^ 0x0 ) << std::endl; std::cout << "0x0 ^ 0x1 = " << ( 0x0 ^ 0x1 ) << std::endl; std::cout << "0x1 ^ 0x0 = " << ( 0x1 ^ 0x0 ) << std::endl; std::cout << "0x1 ^ 0x1 = " << ( 0x1 ^ 0x1 ) << std::endl; 

    La sortie sera

     0x0 ^ 0x0 = 0 0x0 ^ 0x1 = 1 0x1 ^ 0x0 = 1 0x1 ^ 0x1 = 0 

    Donc cette expression

     0 != ( x ^ 0x1 ) 

    sera égal à true seulement quand x! = 0x1.

    Cela ne change pas x lui-même. Il vérifie uniquement si x est égal à 0 ou 1. cette expression pourrait être modifiée en

     if ( x != 0x1 ) 

    Il vérifie que x n’est en fait pas 0x1xor x avec 0x1 entraînera 0 seulement si x est 0x1 … c’est un vieux truc utilisé principalement en langage assembleur

    L’opérateur ^ est xor bitwise. Et 0x1 est le nombre 1 , écrit sous la forme d’une constante hexadécimale.

    Donc, x ^ 0x1 une nouvelle valeur identique à x , mais avec le bit le moins significatif retourné.

    Le code ne fait rien de plus que comparer x avec 1, de manière très compliquée et obscure.

    L’opérateur xor (exclusif ou) est le plus souvent utilisé pour inverser un ou plusieurs bits. L’opération consiste à demander si exactement l’un des bits est un, cela conduit à la table de vérité suivante (A et B sont des entrées, Y est sorti):

     ABY 0 0 0 0 1 1 1 0 1 1 1 0 

    Maintenant, le but de ce code semble être de vérifier si le dernier bit est à 1, et les autres à 0, ce qui est égal à if ( x != 1 ) . La raison de cette méthode obscure pourrait être que les techniques de manipulation de bits antérieures ont été utilisées et peut-être utilisées à d’autres endroits du programme.

    ^ est l’ xor operator dans c . Dans votre cas, x est xor’ed avec 1. Par exemple, x a la valeur 10, alors 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d alors la condition devient vraie.

    Le test binary semble être un obscurcissement délibéré, mais si les données sous-jacentes sont des données d’entreprise provenant d’un système mainframe IBM, il se peut que le code ait été écrit pour refléter la documentation d’origine. Les formats de données IBM remontent aux années 1960 et encodent fréquemment des indicateurs sous forme de bits uniques dans un mot pour économiser le stockage. Comme les formats ont été modifiés, des octets d’indicateur ont été ajoutés à la fin des enregistrements existants pour maintenir la compatibilité ascendante. La documentation d’un enregistrement SMF, par exemple, peut afficher le code du langage d’assemblage pour tester trois bits individuels dans trois mots différents dans un seul enregistrement afin de décider que les données étaient un fichier d’entrée. Je connais beaucoup moins les composants TCP / IP, mais vous pouvez également y trouver des indicateurs de bits.

    L’opérateur ^ est le bit-xor (voir &, |). Le résultat pour une paire de bits est,

     0 ^ 0 == 0 0 ^ 1 == 1 1 ^ 0 == 1 1 ^ 1 == 0 

    Donc l’expression,

     ( x ^ 0x1 ) 

    inverse / retourne le 0ème bit de x (en laissant les autres bits inchangés).

    Considérez si x peut avoir des valeurs en plus de 0x0 et 0x1? Lorsque x est un champ à un seul bit, il ne peut avoir que des valeurs 0x0 et 0x1, mais lorsque x est un int (char / short / long / etc), les bits autres que bit0 peuvent affecter le résultat de l’expression.

    L’expression telle qu’elle est donnée permet aux bits situés à côté du bit 0 d’affecter le résultat,

     if ( 0 != ( x ^ 0x1 ) ) 

    Qui a la véracité équivalente à cette expression (plus simple),

     if ( x ^ 0x1 ) 

    Notez que cette expression examinerait uniquement bit0,

     if( 0x1 & ( x ^ 0x1 ) ) 

    Donc, l’expression telle que présentée combine vraiment deux vérifications d’expression,

     if( ( x & ~0x1 ) //look at all bits besides bit0 || ( x ^ 0x1 ) ) //combine with the xor expression for bit0 

    L’auteur avait-il l’intention de vérifier uniquement bit0 et avait-il voulu utiliser cette expression,

     if( 0x1 & ( x ^ 0x1 ) ) 

    Ou l’auteur a-t-il l’intention de comparer les valeurs de bit1-bitN et de xor de bit0?

    J’ajoute une nouvelle réponse parce que personne n’a vraiment expliqué comment obtenir la réponse de manière intuitive.

    L’inverse de + est - .
    L’inverse de ^ est ^ .

    Comment résolvez-vous 0 != x - 1 pour x ? Vous + 1 aux deux côtés: 0 + 1 != x - 1 + 11 != x
    Comment résolvez-vous 0 != x ^ 1 pour x ? Vous ^ 1 aux deux côtés: 0 ^ 1 != x ^ 1 ^ 11 != x

    J’imagine qu’il y a d’autres bits ou valeurs de champs binarys dans x , et ceci est destiné à tester que seul le bit de poids faible est défini. Dans le contexte, je suppose que c’est la valeur par défaut, et que l’encodage de ceci et certains m associés (probablement plus coûteux à encoder) peuvent être ignorés, car ils doivent tous deux être la valeur par défaut, initialisée dans un constructeur ou similaire. .

    D’une manière ou d’une autre, le décodeur doit pouvoir déduire que ces valeurs sont manquantes. S’ils sont à la fin d’une structure, ils peuvent être communiqués via une valeur de length toujours présente.

    Le XOR est utile dans l’énumération des drapeaux C #. Pour supprimer un seul indicateur de la valeur enum, il est nécessaire d’utiliser l’opérateur xor (référence ici )

    Exemple:

     [Flags] enum FlagTest { None 0x0, Test1 0x1, Test2 0x2, Test3 0x4} FlagTest test = FlagTest.Test2 | FlagTest.Test3; Console.WriteLine(test); //Out: FlagTest.Test2 | FlagTest.Test3 test = test ^ FlagTest.Test2; Console.WriteLine(test); //Out: FlagTest.Test3 

    Il y a beaucoup de bonnes réponses, mais j’aime y penser plus simplement.

     if ( 0 != ( x ^ 0x1 ) ); 

    Tout d’abord. Une instruction if est uniquement false si l’argument est zéro. Cela signifie que la comparaison non nulle est inutile.

     if ( a != 0 ); // Same as if ( a ); 

    Donc, cela nous laisse avec:

     if ( x ^ 0x1 ); 

    Un XOR avec un. Qu’est-ce qu’un XOR fait est essentiellement détecter les bits qui sont différents. Donc, si tous les bits sont identiques, il retournera 0. Comme 0 est faux, le seul moment où il retournera faux est si tous les bits sont identiques. Donc, ce sera faux si les arguments sont les mêmes, true si elles sont différentes … tout comme l’opérateur not égal à .

     if ( x != 0x1 ); 

    En fait, la seule différence entre les deux est que != Renverra 0 ou 1, tandis que ^ retournera n’importe quel nombre, mais la vérité du résultat sera toujours la même. Un moyen facile d’y penser est.

     (b != c) === !!(b ^ c) // for all b and c 

    La “simplification” finale convertit 0x1 en décimal, ce qui équivaut à 1. Par conséquent, votre déclaration est équivalente à:

     if ( x != 1 ) 

    ^ est un opérateur XOR au niveau du bit

    Si x = 1

      00000001 (x) (decimal 1) 00000001 (0x1) (decimal 1) XOR 00000000 (0x0) (decimal 0) 

    ici 0 == (x ^ 0x1)

    Si x = 0

      00000000 (x) (decimal 0) 00000001 (0x1) (decimal 1) XOR 00000001 (0x1) (decimal 0) 

    ici 0! = (x ^ 0x1)

    La table de vérité d’un xor b:

     aba xor b ---------------------------- 1 1 0 1 0 1 0 1 1 0 0 0 

    Le code signifie simplement

    Comme je vois les réponses jusqu’ici manquer une règle simple pour manipuler des s XOR . Sans entrer dans les détails ce que ^ et 0x signifient (et if , et != Etc), l’expression 0 != (x^1) peut être retravaillée comme suit en utilisant le fait que (a^a)==0 :

     0 != (x^1) <=> [xor left and right side by 1] (0^1) != (x^1^1) <=> 1 != x 

    La technique standard qui pourrait être utilisée, ici, est de répéter un idiome tel qu’il apparaît dans le contexte environnant pour plus de clarté, plutôt que de le masquer en le remplaçant par un idiome arithmétiquement plus simple mais dépourvu de sens contextuel.

    Le code environnant peut faire référence fréquemment à (x ^ 1) , ou le test peut demander “si le bit 0 était l’inverse, ce masque serait-il vide?”.

    Étant donné que la condition provoque l’ encode() quelque chose encode() , il se peut que, dans le contexte, l’état par défaut du bit 0 ait été inversé par d’autres facteurs, et il suffit de coder des informations supplémentaires si tout zéro).

    Si vous prenez l’expression hors contexte et demandez ce qu’elle fait, vous ignorez l’intention sous-jacente. Vous pourriez aussi bien regarder la sortie de l’assembly à partir du compilateur et voir qu’elle fait simplement une comparaison directe avec 1.