私は次のコードスニペットに出会いました
if( 0 != ( x ^ 0x1 ) )
encode( x, m );
x ^ 0x1
はどういう意味ですか?これは標準的な手法ですか?
XOR演算(x ^ 0x1
)はビット0を反転します。したがって、式は事実上、xのビット0が0、またはxの他のビットが1であれば、式は真になります。
逆に、x == 1の場合、式はfalseです。
したがって、テストは次と同じです。
if (x != 1)
したがって、(おそらく)不必要に難読化されます。
^
はビット単位 XOR 操作です0x1
は1
が16進表記であるx ^ 0x1
は、x
の最後のビットを反転します(明確でない場合は、上記のリンクのXOR真理値表を参照してください)。したがって、x
が1より大きい場合、またはx
の最後のビットが0の場合、条件(0 != ( x ^ 0x1 ))
は真になります。偽になります。だからそれは同等です
if (x != 1)
P. S.そのような単純な条件を実装する方法の地獄、私は追加するかもしれません。しないでください。複雑なコードを記述する必要がある場合は、コメントを残してください。お願いします。
これは単純化された説明のように思えるかもしれませんが、誰かがゆっくりと説明したい場合は以下のとおりです。
^
は、c、c ++、およびc#の ビットごとのXOR 演算子です。
ビット単位のXORは、等しい長さの2つのビットパターンを取り、対応するビットの各ペアに対して排他的な論理演算OR演算を実行します。
排他的ORは、両方の入力が異なる場合(一方がtrue、他方がfalse)にtrueを出力する論理演算です。
真理値表 ofa xor b:
a b a xor b
----------------------------
1 1 0
1 0 1
0 1 1
0 0 0
バイナリレベルで0 == ( x ^ 0x1 )
式を説明しましょう。
what? xxxxxxxx (8 bits)
xor 00000001 (hex 0x1 or 0x01, decimal 1)
gives 00000000
---------------------------
the only answer is 00000001
そう:
0 == ( x ^ 0x1 ) => x == 1
0 != ( x ^ 0x1 ) => x != 1
排他的なOR(XOR)演算子です。仕組みを理解するために、この簡単なコードを実行できます
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;
出力は
0x0 ^ 0x0 = 0
0x0 ^ 0x1 = 1
0x1 ^ 0x0 = 1
0x1 ^ 0x1 = 0
だからこの表現
0 != ( x ^ 0x1 )
x!= 0x1の場合にのみtrueと等しくなります。
X自体は変更されません。 xが0または1に等しいかどうかのみをチェックします。このrxpressionは次のように変更できます。
if ( x != 0x1 )
x
が実際に0x1
ではないことを確認します... xor
ing x
with 0x1
は、x
が0x1
である場合にのみ0になります...これはほとんど使用される古いトリックですアセンブリ言語で
^
演算子はビット単位のxorです。 0x1
は、16進定数として書かれた1
番号です。
そのため、x ^ 0x1
は、x
と同じ値になりますが、最下位ビットが反転します。
このコードは、非常に複雑であいまいな方法で、xと1を比較するだけです。
Xor(排他的or)演算子は、1つ以上のビットを反転するために最も一般的に使用されます。操作は、ビットの1つが正確に1であるかどうかを確認することです。これにより、次の真理値表が得られます(AとBは入力、Yは出力)。
A B Y
0 0 0
0 1 1
1 0 1
1 1 0
このコードの目的は、最後のビットが1で、他のビットが0であるかどうかを確認することであると思われます。これはif ( x != 1 )
と等しくなります。このあいまいな方法の理由は、以前のビット操作技術が使用されており、おそらくプログラムの他の場所で使用されているためかもしれません。
^
はc
のビット単位のxor operator
です。あなたの場合、xは1とxor'edされます。たとえば、x
の値は10で、10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d
なので条件はtrueになります。
ビットごとのテストは意図的な難読化のようですが、基になるデータがIBMメインフレームシステムからの企業データである場合、元のドキュメントを反映するようにコードが記述されただけである可能性があります。 IBMデータ形式は1960年代に遡り、ストレージを節約するためにWord内のフラグを頻繁に単一ビットとしてエンコードします。形式が変更されると、既存のレコードの末尾にフラグバイトが追加され、後方互換性が維持されます。たとえば、SMFレコードのドキュメントには、単一のレコード内の3つの異なる単語内の3つの個々のビットをテストして、データが入力ファイルであると判断するアセンブリ言語コードが示される場合があります。 TCP/IP内部についてはあまり知りませんが、ビットフラグもあります。
誰も答えを直感的に取得する方法を実際に説明していないため、新しい答えを追加しています。
+
の逆は-
です。^
の逆は^
です。
x
の0 != x - 1
をどのように解決しますか? + 1
両側:0 + 1 != x - 1 + 1
→1 != x
。x
の0 != x ^ 1
をどのように解決しますか? ^ 1
両側:0 ^ 1 != x ^ 1 ^ 1
→1 != x
。
演算子^はビット単位のxorです(&、|を参照)。ビットペアの結果は、
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
だから、式、
( x ^ 0x1 )
xの0番目のビットを反転/反転します(他のビットは変更せずに残します)。
Xが0x0および0x1以外の値を持つことができるかどうかを検討しますか? xが単一ビットフィールドの場合、値は0x0と0x1のみになりますが、xがint(char/short/long/etc)の場合、bit0以外のビットが式の結果に影響を与える可能性があります。
与えられた式により、bit0の横のビットが結果に影響を与えます。
if ( 0 != ( x ^ 0x1 ) )
この(より単純な)式と同等の真実性を持ち、
if ( x ^ 0x1 )
この式はbit0のみを検査することに注意してください。
if( 0x1 & ( x ^ 0x1 ) )
したがって、提示された式は実際に2つの式チェックを組み合わせたものです。
if( ( x & ~0x1 ) //look at all bits besides bit0
|| ( x ^ 0x1 ) ) //combine with the xor expression for bit0
著者はbit0のみをチェックするつもりで、この表現を使用するつもりでしたが、
if( 0x1 & ( x ^ 0x1 ) )
または、著者はbit1-bitNとbit0のxorの値を混ぜるつもりでしたか?
x
には他のビットまたはビットフィールド値があると思いますが、これは下位ビットのみが設定されていることをテストするためのものです。コンテキストでは、これがデフォルトであり、したがって、これといくつかの関連m
(おそらくエンコードするのにより高価な)のエンコードはスキップできます。両方ともデフォルト値でなければならず、コンストラクターなど。
どういうわけか、デコーダはこれらの値が欠落していることを推測できなければなりません。それらが何らかの構造の最後にある場合、常に存在するlength
値を介して通信できます。
良い答えはたくさんありますが、私はもっと簡単に考えたいです。
if ( 0 != ( x ^ 0x1 ) );
まず第一に。 ifステートメントは、引数がゼロの場合のみfalseです。これは、ゼロに等しくないことを比較しても意味がないことを意味します。
if ( a != 0 );
// Same as
if ( a );
したがって、次のようになります。
if ( x ^ 0x1 );
XORと1つ。 XORが行うことは、本質的にはdetect異なるビットです。したがって、すべてのビットが同じである場合、0を返します。0がfalseであるため、falseを返すのは、すべてのビットが同じである場合のみです。したがって、引数が同じ場合はfalseになり、引数が異なる場合はtrueになります... 等しくない演算子のように。
if ( x != 0x1 );
実際、2つの唯一の違いは、!=
が0または1を返すのに対し、^
は任意の数を返すが、結果の真理は常に同じ。それについて考える簡単な方法があります。
(b != c) === !!(b ^ c) // for all b and c
最後の「単純化」は、0x1
を1である10進数に変換することです。したがって、ステートメントは次と同等です。
if ( x != 1 )
XORは、C#フラグ列挙で役立ちます。列挙値から単一のフラグを削除するには、xor演算子を使用する必要があります(参照 ここ )
例:
[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
^は bitwise XOR 演算子です
X = 1の場合
00000001 (x) (decimal 1)
00000001 (0x1) (decimal 1)
XOR 00000000 (0x0) (decimal 0)
ここで0 ==(x ^ 0x1)
X = 0の場合
00000000 (x) (decimal 0)
00000001 (0x1) (decimal 1)
XOR 00000001 (0x1) (decimal 0)
ここ0!=(x ^ 0x1)
Xor bの真理値表:
a b a xor b
----------------------------
1 1 0
1 0 1
0 1 1
0 0 0
コードは単に
ここでmightを使用する標準的な手法は、わかりやすくするために、周囲のコンテキストに表示されるイディオムを繰り返すことです。 。
周囲のコードが(x ^ 1)
を頻繁に参照する場合や、テストで「ビット0が逆の場合、このビットマスクは空になりますか?」.
条件によって何かがencode()
edになる場合、コンテキストではビット0のデフォルト状態が他の要因によって反転されている可能性があり、ビットのいずれかがデフォルトから逸脱している場合のみ追加情報をエンコードする必要があります(通常はすべてゼロ)。
文脈から式を取り出して、それが何をするかを尋ねると、根底にある意図を見落とします。コンパイラーからのAssembly出力を見て、1との直接的な等価比較を行うだけであることがわかります。
これまでのところ、答えはXOR
sを処理するための簡単なルールを見逃しています。 ^
と0x
の意味(およびif
、および!=
など)の詳細を説明せずに、式0 != (x^1)
を次のように作り直すことができます。 (a^a)==0
:
0 != (x^1) <=> [xor left and right side by 1]
(0^1) != (x^1^1) <=>
1 != x