web-dev-qa-db-fra.com

Que signifie (x ^ 0x1)! = 0?

Je suis tombé sur l'extrait de code suivant

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

Qu'est-ce que x ^ 0x1 signifier? Est-ce une technique standard?

183
KodeWarrior

L'opération XOR (x ^ 0x1) inverse le bit 0. L’expression signifie donc réellement: si le bit 0 de x est 0, ou que tout autre bit de x est 1, l’expression est vraie.

Inversement, l'expression est fausse si x == 1.

Donc, le test est le même que:

if (x != 1)

et est donc (sans doute) inutilement obscurcie.

277
Paul R
  • ^ est le bitwise XOR opération
  • 0x1 est 1 en notation hexadécimale
  • x ^ 0x1 _ inversera le dernier bit de x (reportez-vous à la table de vérité XOR du lien ci-dessus si ce n'est pas clair pour vous)).

Donc, la condition (0 != ( x ^ 0x1 )) sera vrai si x est supérieur à 1 ou si le dernier bit de x est 0. Ce qui ne laisse que x == 1 en tant que valeur pour laquelle la condition sera fausse. Donc, cela équivaut à

if (x != 1)

P. S. Enfer d'une façon de mettre en œuvre une telle condition simple, pourrais-je ajouter. Ne fais pas ça. Et si vous devez écrire du code compliqué, laissez un commentaire . Je t'en supplie.

78
Violet Giraffe

Cela peut sembler une explication simplifiée à l'extrême, mais si quelqu'un souhaite le parcourir lentement, voici l'une des explications suivantes:

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

Un bitwise XOR prend deux modèles de bits de longueur égale et effectue l'opération logique exclusive OR sur chaque paire de bits correspondants.

Exclusive OR est une opération logique qui renvoie vrai chaque fois que les deux entrées diffèrent (l'une est vraie, l'autre est fausse).

Le table de vérité de a xor b :

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

Donc, illustrons l'expression 0 == ( x ^ 0x1 ) au niveau binaire:

             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
49
jwaliszko

C'est un opérateur exclusif OR (XOR). Pour comprendre son fonctionnement, 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 à vrai que lorsque x! = 0x1.

Cela ne change pas x lui-même. Il vérifie uniquement si x est égal à 0 ou 1. Cette expression rx pourrait être remplacée par

if ( x != 0x1 )
34
Vlad from Moscow

Il vérifie que x n'est en réalité pas 0x1... xoring x avec 0x1 donnera un 0 seulement si x est 0x1 ... c'est un vieux truc utilisé principalement dans le langage d'assemblage

19
Ferenc Deak

Le ^ l'opérateur est au niveau des bits xor. Et 0x1 est le numéro 1, écrit sous forme de constante hexadécimale.

Alors, x ^ 0x1 évalue 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.

18
David Heffernan

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 une sortie):

A    B    Y
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 bien égal à 1, et que les autres sont à 0, cela équivaut à if ( x != 1 ). La raison de cette méthode obscure pourrait être que des techniques de manipulation de bits antérieures ont été utilisées et sont peut-être utilisées à d’autres endroits du programme.

11
Paul

^ est bitwise xor operator dans c. Dans votre cas, x est xoré avec 1. Par exemple, x a la valeur 10, puis 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d donc la condition devient vraie.

8
Chinna

Le test au niveau du bit 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 simplement 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 codent souvent les indicateurs sous forme de bits uniques dans un mot pour économiser le stockage. Au fur et à mesure de la modification des formats, des octets de drapeau ont été ajoutés à la fin des enregistrements existants afin de préserver la compatibilité avec les versions antérieures. La documentation d'un enregistrement SMF, par exemple, peut indiquer le code de langue d'assemblage pour tester trois bits individuels dans trois mots différents dans un seul enregistrement afin de décider que les données sont un fichier d'entrée. J'en sais beaucoup moins sur les composants internes TCP/IP, mais vous pouvez également y trouver des indicateurs de bits.

8
undefined

J'ajoute une nouvelle réponse car 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? Toi + 1 des deux côtés: 0 + 1 != x - 1 + 11 != x.
Comment résolvez-vous 0 != x ^ 1 pour x? Toi ^ 1 des deux côtés: 0 ^ 1 != x ^ 1 ^ 11 != x.

7
Mehrdad

L'opérateur ^ est le bitwise-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).

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

L’expression donnée permet aux bits situés à côté de bit0 d’affecter le résultat,

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

Qui a une vérité é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 réellement deux contrôles 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 ne vérifier que bit0 et avait-il l'intention d'utiliser cette expression?

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

Ou l’auteur at-il l’intention de combiner les valeurs de bit1-bitN et le xor de bit0?

7
ChuckCottrill

Je suppose qu'il y a d'autres bits ou valeurs de champ de bits 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, par conséquent, le codage de ceci et de certains m connexes (probablement plus coûteux à coder) peut être ignoré, 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. Si elles sont à la fin d'une structure, elles peuvent être communiquées via une valeur length toujours présente.

6
Ed Staub

Il y a beaucoup de bonnes réponses mais j'aime y penser d'une manière plus simple.

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

Tout d'abord. Une instruction if n'est fausse que si l'argument est zéro. Cela signifie que comparer non égal à zéro est inutile.

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

Cela nous laisse donc:

if ( x ^ 0x1 );

Un XOR avec un. Qu'est-ce qu'un XOR fait est essentiellement détecter bits qui sont différents. Donc, si tous les bits sont les idem retournera 0. Comme 0 est faux, la seule fois où il retournera faux, c’est si tous les bits sont identiques, donc si les arguments sont les mêmes, vrai si ils sont différents ... tout comme l'opérateur différent de.

if ( x != 0x1 );

En fait, la seule différence entre les deux est que != retournera 0 ou 1, tandis que ^ retournera n'importe quel nombre, mais le vérité du résultat sera toujours le 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 qui est 1. Par conséquent, votre déclaration équivaut à:

if ( x != 1 )
4
Kevin Cox

Le XOR est utile dans l’énumération de drapeau C #. Pour supprimer un indicateur unique de la valeur d’énumération, 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
4
Igrek.

^ est un opérateur bit à bit XOR

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:

a           b        a xor b
----------------------------
1           1           0
1           0           1
0           1           1
0           0           0

Le code signifie simplement

1
akbar ali

La technique standard qui peut-être être utilisée ici est de répéter un idiome tel qu'il apparaît dans un contexte apparent par souci de clarté, plutôt que de l'obscurcir en le remplaçant par un idiome arithmétiquement plus simple mais sans signification contextuelle .

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

Étant donné que la condition cause quelque chose à être encode() ed, il se peut que dans le contexte, l'état par défaut du bit 0 ait été inversé par d'autres facteurs, et nous n'avons besoin de coder que des informations supplémentaires si l'un des bits dévie de leur valeur. défaut (normalement tout à zéro).

Si vous prenez l'expression hors contexte et demandez ce qu'elle fait, vous oubliez l'intention sous-jacente. Vous pourriez aussi bien regarder la sortie de l'assembly du compilateur et constater qu'elle effectue simplement une comparaison directe de l'égalité avec 1.

1
sh1

Comme je vois les réponses à ce jour, rater une règle simple pour gérer XORs. Sans entrer dans les détails que signifient ^ Et 0x (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
0
Serge Rogatch