(x ^ 0x1)!= 0はどういう意味ですか?


183

私は次のコードスニペットに出くわしました

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

どういうx ^ 0x1意味ですか?これは標準的なテクニックですか?


97
コードの難読化は非常に標準的です。
raina77ow 2013

47
これは、「通常の」式と同じ手法を用いて解くことができる:0 != (x ^ 1)→XOR両側1→によって(0 ^ 1) != (x ^ 1 ^ 1)→簡素化→1 != x
Score_Under

4
if (1 != x)書くのがいかに難しいかわかりません。
Adriano Varoli Piazza

12
最初に@Spookによるさまざまなコメントは、typeof xが指定されていないことを明確に指摘しています-したがって、これがこのC ++タグ付き問題の整数であることはわかりません。確かに、これがCまたはx整数の場合、答えは簡単ですが、それは与えられておらず、過負荷の可能性がありoperator ^ます。
chux-モニカを

11
これがどうして多くの賛成票を獲得するのかわかりません...
laike9m

回答:


277

XOR演算(x ^ 0x1)はビット0を反転します。したがって、式は事実上、xのビット0が0、またはxの他のビットが1の場合、式は真になります。

逆に、x == 1の場合、式はfalseです。

したがって、テストは次と同じです。

if (x != 1)

したがって、(おそらく)不必要に難読化されます。


39
ねえ、あなたはコンテキストを知りません。xが何らかのビットフラグである場合、IMOは、!=演算子を使用するよりも、今のようにそれを書き込む方が実際にはより明確です。
幽霊

40
@Spook:シングルビットフラグをテストするだけではなく、xの幅全体をテストします。単一のビットをテストするだけの場合は、ビットごとのANDを使用するなど、より明確なイディオムがあります。
Paul R

115
不必要に難読化されましたか?コードを難読化するのが私たちの仕事であることを知らないのですか。だれでも理解できる簡単なコードを書いたとしたら、なぜ、世界における私たちの立場の宗教的神聖さはどこに行くのでしょうか。私たちは突然、他の皆と同じように一般労働者になるでしょう。難読化は本質的に必要です。
Thom

31
実際にSpookは正しいです。テスト(x!= 1)は同等ではありません。コードはC ++にすることができます(C ++では、^は何でもできる演算子にすることができます)。だからあなたはコンテキストを知りません、@ Spookは正しいです。
xryl669 2013

82
@TheThomуєтуσυωяιтєιи¢ℓєαятєχт
bobobobo

78
  • ^ビットごとのXOR演算です
  • 0x1ある116進表記で
  • x ^ 0x1の最後のビットを反転しますx(明確でない場合は、上のリンクのXOR真理値表を参照してください)。

したがって、が1より大きい場合、またはの最後のビットが0の(0 != ( x ^ 0x1 ))場合、条件はtrue になります。これは、条件がfalseになる値としてx == 1のみを残します。したがって、次と同等ですxx

if (x != 1)

そのような単純な条件を実装する方法のPS Hellを付け加えます。しないでください。複雑なコードを書く必要がある場合は、コメントを残してください。お願いします。


7
そうではありませんx==04 ^ 0x1真ですが、4==0明らかに偽です。
Fred Foo

4
「状態は次のように見えるif (x == 0)」、それと同じではありませんx != 1か?
Andrew-Dufresne

6
同値は、それxが整数型であることを前提としています。それはだ場合floatdouble、その後、私は式が真のためにもたらすであろうと考えています1.0 <= x < 2.0。IFおよびxユーザー定義型である場合、式はtrueを返すことができxユーゴ、カンガルー、有名な作曲家の誕生日、または中国のお茶の現在のドル建て価格で株式少なくとも3桁の任意の数です。
スーパーキャット2013

4
@supercat operator^for float/ はありませんdouble
ふわふわした

1
@supercat:浮動小数点から整数への変換が要求されると、変換は暗黙的に行われます(キャスト構文は必要ありません)。ただし、ビットごとの演算子によって変換がトリガーされることはありません。浮動小数点型の場合は失敗します。
Ben Voigt

49

これは単純化した説明のように見えるかもしれませんが、誰かがゆっくりとそれをやりたい場合は、以下に示します:

^あるビット単位のXORの C、C ++やC#でのオペレータが。

ビット単位のXORは、同じ長さの2つのビットパターンを取り、対応するビットの各ペアに対して論理排他的OR演算を実行します。

排他的ORは、両方の入力が異なる場合は常にtrueを出力する論理演算です(一方はtrue、もう一方はfalse)。

真理値表排他的論理和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

34

排他的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 )

19

それをチェックしx、実際にされていません0x1... xorINGのx0x1あれば0になりますが唯一xである0x1...これは主に、アセンブリ言語で使われていた古いトリックです


これはより速いです!= 1か?
ビット

2
私の記憶が正しければ、手動アセンブリの最適化(x86の)をしながら古代にxorアプローチが少ないマシンコードを含んでおり、より迅速に対応する割り当てよりも実行されました0...しかし、この質問は含まxor私はと思うかもしれないので、比較する!=かもしれませんもっと早く。ただし、コンパイラが生成したアセンブリを確認する必要があるかどうかは、よくわかりません。
Ferenc Deak

10
@BitFiddlingCodeMonkey:いいえ。XORがネイティブレベルの同等性テストよりも高速である場合、コンパイラーはXORを発行して同等性をテストします。したがって、XORはコンパイラの最適化に関する同等性テストよりも速くなることはありません。高速なコードを作成するルール101は、「コンパイラーを試して助けてはいけません。実際には、読み取り速度の遅いコードを作成するだけです。」
Matt

@fritzone IIRC、XORトリックはレジスタの保存に多くの関係があり、レジスタロードの保存はリテラルをOPで直接エンコードできる場合があり、ステータスフラグとの微妙な違いがいくつかありました(ただし、私のアセンブリのほとんどはオンでした) 68kおよびDSP)。
mpdonadio 2013

1
@MPD:通常は、レジスタをクリアすることです(少なくとも386以上)。xor eax、eaxは2バイトでeaxをゼロに設定しますが、mov eax、0は3または6バイト(エンコーディングに応じて)を要し、xor形式よりもデコードにわずかに時間がかかります。
Matt

18

^オペレータは、ビット単位の排他的論理和です。そして0x1数である1進定数として書かれました、。

したがって、x ^ 0x1と同じ新しい値に評価されますが、x最下位ビットが反転します。

このコードは、xを1と比較するだけで、非常に複雑であいまいな方法で行われます。


11

xor(排他的論理和)演算子は、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 )。これはに等しいです。このあいまいな方法の理由は、以前のビット操作技法が使用されており、プログラムの他の場所で使用されている可能性があるためです。


8

^はビット単位xor operatorですc。あなたの場合、xは1でxorされます。たとえばx、値が10の場合10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11d、条件はtrueになります。


あなたの答えの誤植。10 != 1010
ビット

@BitFiddlingCodeMonkey:コメントの誤植:10 (decimal) == 1010 (binary)
Paul R

6
@PaulRあなたがbそこに何かを入れない場合、誰がどのように10進数と2進数が何であるかを知っているはずですか?
ビット

0b1010はPythonicの方法ではないでしょうか?
TankorSmash 2013

8

ビット単位のテストは意図的な難読化のようですが、基礎となるデータがIBMメインフレームシステムからの企業データである場合は、コードが元のドキュメントを反映するように作成された可能性があります。IBMのデータ形式は1960年代にさかのぼり、ストレージを節約するためにフラグをワード内の単一ビットとして頻繁にエンコードします。フォーマットが変更されると、下位互換性を維持するために、既存のレコードの最後にフラグバイトが追加されました。たとえば、SMFレコードのドキュメントには、データが入力ファイルであると判断するために、1つのレコード内の3つの異なるワード内の3つの個別のビットをテストするアセンブリ言語コードが示されている場合があります。TCP / IPの内部についてはあまり詳しくありませんが、ビットフラグもそこにあるかもしれません。


7

演算子^はビット単位の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の値を混同するつもりでしたか?


7

答えを直感的に取得する方法を誰も実際に説明しなかったので、新しい答えを追加します。

の逆は+です-
の逆^^

どのように解決0 != x - 1xますか?あなた+ 1は両側に:0 + 1 != x - 1 + 11 != x
どのように解決0 != x ^ 1xますか?あなた^ 1は両側に:0 ^ 1 != x ^ 1 ^ 11 != x


6

には他のビットまたはビットフィールド値があると思います。xこれは、下位ビットのみが設定されていることをテストすることを目的としています。コンテキストでは、これがデフォルトであるため、このエンコードと関連するm(おそらくエンコードにコストがかかる)のエンコーディングはスキップできます。両方ともデフォルト値であり、コンストラクターなどで初期化されている必要があるためです。

どういうわけか、デコーダーはこれらの値が欠落していることを推測できなければなりません。それらが何らかの構造の最後にある場合は、length常に存在する値を介して通信される可能性があります。


4

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


@theDmi:ビット操作とビットマスクについても。C#のフラグ列挙型は、ビットマスクに関するものです。
Igrek。

さらに、C ++でも役立ちます。参照:スタック1 および スタック2
Igrek。

この答えは、ビットごとのXOR演算子についての議論以外は、元の質問とは関係がないようです。
Paul R

4

良い答えはたくさんありますが、もっと簡単に考えたいと思います。

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

まず第一に。ifステートメントは、引数がゼロの場合にのみ偽になります。これは、ゼロに等しくない比較は無意味であることを意味します。

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

これで、次のことが可能になります。

if ( x ^ 0x1 );

1つのXOR。XORが行うことは、本質的に異なるビットを検出することです。したがって、すべてのビットが同じである場合、0を返します。0がfalseであるため、falseを返すのは、すべてのビットが同じである場合のみです。それはfalseになりますので、それらが異なる場合...同じような引数は、真の同じであれば、ないに等しい演算子。

if ( x != 0x1 );

事実、2つの違いは!=0または1 ^を返すだけで、任意の数値を返しますが、結果の真実性は常に同じです。それについて考える簡単な方法です。

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

最後の「単純化」は、0x11である10進数に変換することです。したがって、ステートメントは次と同等です。

if ( x != 1 )

1

^はビットごとの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

コードは単に意味します


6
さらに別の回答を投稿する必要がありますか?
Mysticial 2013

2
別の答えを言うことはできますが、重複することはできません。ご
了承

1

かもしれない標準的な技術ここで使用されあるは、算術的に単純であるが文脈上無意味なイディオムで置き換えることによって難読化するのではなく、明確にするために周囲の文脈で現れるイディオムを繰り返すことです。

周囲のコードがを頻繁に参照する(x ^ 1)か、テストで「ビット0が逆の場合、このビットマスクは空になりますか?」

条件が何かを引き起こすことを考えると encode()編集場合、コンテキストではビット0のデフォルト状態が他の要因によって反転されている可能性があり、ビットのいずれかがデフォルト(通常はすべてゼロ)から逸脱している場合にのみ、追加情報をエンコードする必要があります)。

表現を文脈から外してそれが何をするかを尋ねると、根本的な意図を見落とすことになります。コンパイラからのアセンブリ出力を見て、単に1との直接の等価比較を行っていることもわかるでしょう。


0

これまでの回答を見ると、XORs を処理するための単純なルールがありません。意味^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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.