Je suis tombé sur l'extrait de code suivant
if( 0 != ( x ^ 0x1 ) )
encode( x, m );
Que veut x ^ 0x1
dire? Est-ce une technique standard?
c++
c
bit-manipulation
bitmask
KodeWarrior
la source
la source
0 != (x ^ 1)
→ xou les deux côtés par 1 →(0 ^ 1) != (x ^ 1 ^ 1)
→ simplifier →1 != x
if (1 != x)
est difficile d'écrire.type
ofx
n'est pas donné - par conséquent, nous ne savons pas qu'il s'agit d'un entier dans ce problème étiqueté C ++. Bien sûr, si c'est C oux
est un entier, la réponse est facile, mais ce n'est pas une donnée et la possibilité de surchargeoperator ^
existe.Réponses:
L'opération XOR (
x ^ 0x1
) inverse le bit 0. Ainsi, l'expression signifie en fait: si le bit 0 de x est 0, ou tout autre bit de x est 1, alors l'expression est vraie.Inversement, l'expression est fausse si x == 1.
Le test est donc le même que:
if (x != 1)
et est donc (sans doute) inutilement obscurcie.
la source
^
est le niveau du bit XOR opération0x1
est1
en notation hexadécimalex ^ 0x1
va inverser le dernier bit dex
(reportez-vous à la table de vérité XOR dans le lien ci-dessus si ce n'est pas clair pour vous).Ainsi, la condition
(0 != ( x ^ 0x1 ))
sera vraie six
est supérieure à 1 ou si le dernier bit dex
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'un moyen de mettre en œuvre une condition aussi simple, pourrais-je ajouter. Ne fais pas ça. Et si vous devez écrire du code compliqué, laissez un commentaire . Je t'en supplie.
la source
x==0
;4 ^ 0x1
est vrai, mais4==0
est évidemment faux.if (x == 0)
", n'est-ce pas égal àx != 1
?x
s'agit d'un type intégral. Si c'est unfloat
oudouble
, alors je crois que l'expression donnerait vrai pour1.0 <= x < 2.0
. Et six
est un type défini par l'utilisateur, l'expression peut retourner true six
est un Yugo, un kangourou, l'anniversaire d'un célèbre compositeur ou tout autre nombre qui partage au moins trois chiffres avec le prix actuel du thé en dollars en Chine.operator^
pourfloat
/double
.Cela peut sembler une explication trop simpliste, mais si quelqu'un souhaite la parcourir lentement, c'est ci-dessous:
^
est un opérateur XOR au niveau du bit en c, c ++ et c #.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
Illustrons donc l'
0 == ( x ^ 0x1 )
expression au niveau binaire:what? xxxxxxxx (8 bits) xor 00000001 (hex 0x1 or 0x01, decimal 1) gives 00000000 --------------------------- the only answer is 00000001
donc:
0 == ( x ^ 0x1 ) => x == 1 0 != ( x ^ 0x1 ) => x != 1
la source
Il s'agit d'un opérateur OU (XOR) exclusif. 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 à vrai uniquement lorsque x! = 0x1.
Il ne change pas x lui-même. Il vérifie seulement si x est égal à 0 ou à 1. cette expression r peut être changée en
if ( x != 0x1 )
la source
Il vérifie que
x
est en fait pas0x1
...xor
INGx
avec0x1
entraînera 0 seulement six
est0x1
... c'est un vieux truc utilisé principalement en langage assembleurla source
!= 1
?xor
approche contenait moins de code machine et était exécutée plus rapidement que l'affectation correspondante à0
... mais cette question contient unxor
ET une comparaison, donc je pourrais penser que cela!=
pourrait être plus rapide. Je ne suis pas si sûr cependant que j'aurais besoin de voir un assemblage généré par le compilateur.L'
^
opérateur est xor au niveau du bit. Et0x1
est le nombre1
, écrit sous forme de constante hexadécimale.Donc,
x ^ 0x1
évalue à une nouvelle valeur qui est la même quex
, mais avec le bit le moins significatif inversé.Le code ne fait rien de plus que comparer x à 1, d'une manière très compliquée et obscure.
la source
L'opérateur xor (ou exclusif) est le plus couramment 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 exactement le dernier bit est 1, et les autres sont 0, cela est égal
if ( x != 1 )
. La raison de cette méthode obscure pourrait être que des techniques antérieures de manipulation de bits ont été utilisées et sont peut-être utilisées à d'autres endroits du programme.la source
^
est bitwisexor operator
dansc
. Dans votre cas, x est xor'ed avec 1. par exemplex
a la valeur 10, alors la10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d
condition devient vraie.la source
10 != 1010
10 (decimal) == 1010 (binary)
b
ou quelque chose?Le test au niveau du bit semble être une obfuscation délibérée, mais si les données sous-jacentes sont des données d'entreprise 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 fréquemment des indicateurs sous forme de bits uniques dans un mot pour économiser le stockage. Au fur et à mesure que les formats étaient 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 sont un fichier d'entrée. J'en sais beaucoup moins sur les composants internes TCP / IP, mais vous pouvez également y trouver des bits indicateurs.
la source
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 autres que 0x0 et 0x1? Lorsque x est un champ à un seul bit, il ne peut avoir que les valeurs 0x0 et 0x1, mais lorsque x est un entier (char / short / long / etc), les bits en plus de bit0 peuvent affecter le résultat de l'expression.
L'expression telle que donnée permet aux bits à côté de bit0 d'affecter le résultat,
if ( 0 != ( x ^ 0x1 ) )
Qui a une véracité équivalente à cette expression (plus simple),
if ( x ^ 0x1 )
Notez que cette expression n'examinerait que bit0,
if( 0x1 & ( x ^ 0x1 ) )
L'expression telle que présentée combine en réalité 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 vérifier uniquement bit0, et a-t-il voulu utiliser cette expression,
if( 0x1 & ( x ^ 0x1 ) )
Ou est-ce que l'auteur avait l'intention de combiner les valeurs de bit1-bitN et le xor de bit0?
la source
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 allez-vous résoudre
0 != x - 1
pourx
? Vous+ 1
des deux côtés:0 + 1 != x - 1 + 1
→1 != x
.Comment allez-vous résoudre
0 != x ^ 1
pourx
? Vous^ 1
des deux côtés:0 ^ 1 != x ^ 1 ^ 1
→1 != x
.la source
Je suppose qu'il y a d'autres bits ou valeurs de champ de bits
x
, et cela 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, l'encodage de ceci et de certains connexesm
(probablement plus coûteux à encoder) peut être ignoré, car ils doivent tous les 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 être capable de déduire que ces valeurs sont manquantes. S'ils sont à la fin d'une structure, cela peut être communiqué via une
length
valeur toujours présente.la source
Le XOR est utile dans l'énumération d'indicateur C #. Pour supprimer l'indicateur unique 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
la source
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 );
Donc, cela nous laisse avec:
if ( x ^ 0x1 );
Un XOR avec un. Ce que fait un XOR est essentiellement de détecter les bits qui sont différents. Donc, si tous les bits sont identiques, il renverra 0. Puisque 0 est faux, la seule fois où il retournera faux est si tous les bits sont identiques. Donc, ce sera faux si les arguments sont les mêmes, vrai s'ils sont différents ... tout comme l' opérateur pas égal à .
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 la véracité du résultat sera toujours la même. Une façon simple d'y penser est.(b != c) === !!(b ^ c) // for all b and c
La "simplification" finale est la conversion
0x1
en décimal qui est 1. Par conséquent, votre déclaration équivaut à:if ( x != 1 )
la source
^ 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:
a b a xor b ---------------------------- 1 1 0 1 0 1 0 1 1 0 0 0
Le code signifie simplement
la source
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 qui est 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, est-ce que ce masque de bits serait vide?".Étant donné que la condition provoque une modification de 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 nous n'avons besoin d'encoder des informations supplémentaires que si l'un des bits s'écarte de leur valeur par défaut (normalement tout zéro ).Si vous sortez l'expression de son contexte et demandez ce qu'elle fait, vous oubliez l'intention sous-jacente. Vous pouvez tout aussi bien regarder la sortie d'assembly du compilateur et voir qu'elle fait simplement une comparaison d'égalité directe avec 1.
la source
Comme je vois les réponses jusqu'à présent, il manque une règle simple pour traiter l'
XOR
art. Sans entrer dans les détails de ce que^
et0x
signifient (etif
, et!=
etc.), l'expression0 != (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 source