Apa artinya (x ^ 0x1)! = 0 artinya?

183

Saya menemukan potongan kode berikut

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

Apa x ^ 0x1artinya Apakah ini beberapa teknik standar?

Prajurit Kode
sumber
97
Kebingungan kode cukup standar.
raina77ow
47
Ini dapat diselesaikan dengan pendekatan yang sama dengan persamaan "normal": 0 != (x ^ 1)→ xor kedua sisi dengan 1 → (0 ^ 1) != (x ^ 1 ^ 1)→ sederhanakan →1 != x
Score_Under
4
Saya tidak mengerti betapa if (1 != x)sulitnya menulis.
Adriano Varoli Piazza
12
Berbagai komentar, pertama dengan @Spook, jelas menunjukkan bahwa typedari xtidak diberikan - maka kita tidak tahu ini adalah bilangan bulat di C ini ++ ditandai masalah. Tentu, jika ini adalah C atau xbilangan bulat, jawabannya mudah, tetapi itu tidak diberikan dan kemungkinan kelebihan beban operator ^ada.
chux - Reinstate Monica
11
Saya tidak melihat bagaimana ini mendapatkan begitu banyak upvotes ...
laike9m

Jawaban:

277

Operasi XOR ( x ^ 0x1) membalikkan bit 0. Jadi ekspresi secara efektif berarti: jika bit 0 dari x adalah 0, atau bit x lainnya adalah 1, maka ekspresi itu benar.

Sebaliknya ungkapan itu salah jika x == 1.

Jadi tesnya sama dengan:

if (x != 1)

dan karena itu (bisa dibilang) tidak perlu dikaburkan.

Paul R
sumber
39
Hei, kamu tidak tahu konteksnya. Jika x adalah semacam bit flag, sebenarnya IMO lebih jelas untuk menuliskannya seperti sekarang daripada menggunakan operator! =.
Spook
40
@Spook: ini bukan hanya menguji bit bendera tunggal - itu menguji seluruh lebar x. Jika Anda hanya ingin menguji sedikit saja maka ada idiom yang lebih jelas, seperti menggunakan bitwise AND.
Paul R
115
Tidak perlu dikaburkan? Apakah kamu tidak tahu bahwa itu adalah tugas kita untuk mengaburkan kode. Jika kita menulis kode sederhana yang dapat dipahami siapa pun, mengapa, ke mana perginya kesucian agama dari posisi kita di dunia? Kami tiba-tiba menjadi pekerja biasa seperti orang lain. Kebingungan secara inheren diperlukan.
Thom
31
Sebenarnya Spook benar. Tes (x! = 1) tidak setara. Kode dapat berupa C ++ (dan dalam C ++, ^ dapat menjadi operator yang melakukan apa saja). Jadi Anda tidak tahu konteksnya, @Spook benar.
xryl669
82
@TheThom уєт уσυ ωяιтє ιи ¢ ℓєαя тєχт
bobobobo
78
  • ^adalah operasi XOR bitwise
  • 0x1adalah 1dalam notasi hex
  • x ^ 0x1akan membalikkan bit terakhir x(lihat tabel kebenaran XOR di tautan di atas jika itu tidak jelas bagi Anda).

Jadi, kondisi (0 != ( x ^ 0x1 ))akan benar jika xlebih besar dari 1 atau jika bit terakhir xadalah 0. Yang hanya menyisakan x == 1 sebagai nilai di mana kondisi tersebut akan salah. Jadi itu setara dengan

if (x != 1)

PS Neraka cara untuk menerapkan kondisi sederhana seperti itu, saya dapat menambahkan. Jangan lakukan itu. Dan jika Anda harus menulis kode yang rumit, tinggalkan komentar . Aku mohon padamu.

Violet Giraffe
sumber
7
Bukan x==0; 4 ^ 0x1itu benar, tetapi 4==0jelas salah.
Fred Foo
4
"kondisi tampaknya sama dengan if (x == 0)", bukankah itu sama dengan x != 1?
Andrew-Dufresne
6
Kesetaraan mengandaikan bahwa itu xadalah tipe integral. Jika a floatatau double, maka saya percaya ungkapan itu akan menghasilkan true for 1.0 <= x < 2.0. Dan jika xadalah tipe yang ditentukan pengguna, ungkapan itu bisa kembali benar jika xadalah Yugo, kanguru, ulang tahun komposer terkenal, atau angka apa pun yang berbagi setidaknya tiga digit dengan harga teh dalam mata uang dolar saat ini di Cina.
supercat
4
@supercat Tidak ada operator^untuk float/ double.
lembut
1
@supercat: Ketika konversi dari floating-point ke integer dipanggil, konversi adalah implisit (tidak memerlukan sintaksis cast). Tetapi tidak ada konversi yang dipicu oleh operator bitwise, mereka hanya gagal untuk tipe floating-point.
Ben Voigt
49

Ini mungkin tampak sebagai penjelasan yang terlalu disederhanakan, tetapi jika seseorang ingin menjalaninya secara perlahan, maka di bawah ini:

^adalah operator XOR bitwise dalam c, c ++ dan c #.

Bitor XOR mengambil dua pola bit dengan panjang yang sama dan melakukan operasi ATAU eksklusif logis pada setiap pasangan bit yang sesuai.

Eksklusif ATAU adalah operasi logis yang menghasilkan true ketika kedua input berbeda (satu benar, yang lain salah).

The tabel kebenaran dari suatu xor b :

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

Jadi mari kita ilustrasikan 0 == ( x ^ 0x1 )ekspresi pada tingkat biner:

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

begitu:

   0 == ( x ^ 0x1 )    =>    x == 1
   0 != ( x ^ 0x1 )    =>    x != 1
jwaliszko
sumber
34

Ini adalah operator eksklusif ATAU (XOR). Untuk memahami cara kerjanya, Anda dapat menjalankan kode sederhana ini

    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;

Outputnya adalah

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

Jadi ungkapan ini

0 != ( x ^ 0x1 )

akan sama dengan benar hanya ketika x! = 0x1.

Itu tidak mengubah x itu sendiri. Ini hanya memeriksa apakah x sama dengan 0 atau 1. rxpression ini dapat diubah menjadi

if ( x != 0x1 )
Vlad dari Moskow
sumber
19

Hal cek yang xsebenarnya tidak 0x1... xoring xdengan 0x1akan menghasilkan 0 hanya jika xadalah 0x1... ini adalah trik lama banyak digunakan dalam bahasa assembly

Ferenc Deak
sumber
Apakah ini lebih cepat daripada != 1?
Fiddling Bits
2
di zaman kuno saat melakukan optimasi perakitan manual (x86) jika saya ingat dengan benar xorpendekatan tersebut mengandung lebih sedikit kode mesin dan dieksekusi lebih cepat daripada penugasan yang sesuai untuk 0... namun pertanyaan ini berisi xorDAN perbandingan, jadi saya mungkin berpikir bahwa !=mungkin lebih cepat. Namun saya tidak begitu yakin, perlu melihat beberapa kompiler yang dihasilkan perakitan.
Ferenc Deak
10
@ BitFiddlingCodeMonkey: Tidak. Jika XOR lebih cepat dari beberapa tes kesetaraan tingkat asli, kompiler Anda akan memancarkan XOR untuk menguji kesetaraan. Oleh karena itu, XOR tidak pernah lebih cepat dari tes kesetaraan untuk mengoptimalkan kompiler. Aturan 101 penulisan kode cepat adalah "jangan coba-coba dan bantu kompiler. Anda hanya akan berakhir membuat kode yang tidak dapat dibaca yang lebih lambat dalam praktiknya".
Matt
@fritzone IIRC, trik XOR lebih berkaitan dengan menyimpan register, menghemat beban register b / c literal dapat dikodekan langsung dalam OP dalam beberapa kasus, dan beberapa perbedaan halus dengan bendera status (tetapi sebagian besar perakitan saya aktif 68k dan DSP).
mpdonadio
1
@ MPD: Biasanya ini ada hubungannya dengan membersihkan register (setidaknya di 386+). xor eax, eax menetapkan eax ke nol dalam dua byte, tetapi mov eax, 0 membutuhkan tiga atau enam byte (tergantung pada enkode), dan membutuhkan sedikit lebih lama untuk memecahkan kode daripada bentuk xor .
Matt
18

The ^operator adalah bitwise XOR. Dan 0x1adalah bilangan 1, ditulis sebagai konstanta heksadesimal.

Jadi, x ^ 0x1evaluasi ke nilai baru yang sama dengan x, tetapi dengan bit paling tidak signifikan terbalik.

Kode tidak lebih dari membandingkan x dengan 1, dengan cara yang sangat berbelit-belit dan tidak jelas.

David Heffernan
sumber
11

Operator xor (eksklusif atau) paling sering digunakan untuk membalikkan satu atau lebih bit. Operasi ini untuk menanyakan apakah salah satu bitnya adalah satu, ini mengarah ke tabel kebenaran berikut (A dan B adalah input, Y adalah output):

A    B    Y
0    0    0
0    1    1
1    0    1
1    1    0

Sekarang tujuan dari kode ini tampaknya untuk memeriksa apakah bit terakhir adalah 1, dan yang lainnya adalah 0, ini sama dengan if ( x != 1 ). Alasan untuk metode yang tidak jelas ini mungkin karena teknik manipulasi bit sebelumnya telah digunakan dan mungkin digunakan di tempat lain dalam program.

Paul
sumber
8

^bitwise xor operatordalam c. Dalam kasus Anda x adalah xor'ed dengan 1. misalnya xmemiliki nilai 10, maka 10d ^ 1d ===> 1010b ^ 0001b = 1011b, 1011b == 11dkondisi menjadi benar.

Chinna
sumber
Ketikkan jawaban Anda. 10 != 1010
Fiddling Bits
@ BitFiddlingCodeMonkey: ketikkan komentar Anda:10 (decimal) == 1010 (binary)
Paul R
6
@ PaulR Bagaimana orang seharusnya tahu apa yang desimal dan apa yang biner jika Anda tidak meletakkan batau sesuatu di sana?
Fiddling Bits
bukankah 0b1010 akan menjadi cara Pythonic dalam melakukan sesuatu?
TankorSmash
8

Tes bitwise tampaknya merupakan kebingungan yang disengaja, tetapi jika data yang mendasarinya adalah data perusahaan dari sistem mainframe IBM, mungkin saja kode tersebut ditulis untuk mencerminkan dokumentasi asli. Format data IBM kembali ke tahun 1960-an dan sering menyandikan bendera sebagai bit tunggal dalam sebuah kata untuk menghemat penyimpanan. Saat format diubah, flag bytes ditambahkan di akhir catatan yang ada untuk menjaga kompatibilitas. Dokumentasi untuk catatan SMF, misalnya, mungkin menunjukkan kode bahasa rakitan untuk menguji tiga bit individual dalam tiga kata berbeda dalam satu catatan tunggal untuk memutuskan bahwa data tersebut adalah file input. Saya tahu sedikit tentang TCP / IP internal, tetapi Anda mungkin menemukan flag bit di sana, juga.

tidak terdefinisi
sumber
7

Operator ^ adalah bitwise-xor (lihat &, |). Hasil untuk pasangan bit adalah,

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

Jadi ungkapannya,

( x ^ 0x1 )

membalikkan / membalik bit ke 0 x (membiarkan bit lainnya tidak berubah).

Pertimbangkan apakah x dapat memiliki nilai selain 0x0 dan 0x1? Ketika x adalah bidang bit tunggal, ia hanya dapat memiliki nilai 0x0 dan 0x1, tetapi ketika x adalah int (char / short / long / etc), bit selain bit0 dapat memengaruhi hasil ekspresi.

Ekspresi seperti yang diberikan memungkinkan bit di samping bit0 untuk mempengaruhi hasilnya,

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

Yang memiliki kebenaran setara dengan ungkapan (sederhana) ini,

if ( x ^ 0x1 )

Perhatikan bahwa ungkapan ini hanya akan memeriksa bit0,

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

Jadi ekspresi yang disajikan benar-benar menggabungkan dua pemeriksaan ekspresi,

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

Apakah penulis hanya bermaksud memeriksa bit0, dan bermaksud menggunakan ungkapan ini,

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

Atau apakah penulis bermaksud menggandakan nilai untuk bit1-bitN dan xor dari bit0?

ChuckCottrill
sumber
7

Saya menambahkan jawaban baru karena tidak ada yang benar-benar menjelaskan cara mendapatkan jawaban secara intuitif.

Kebalikannya +adalah -.
Kebalikannya ^adalah ^.

Bagaimana Anda mengatasi 0 != x - 1untuk x? Anda di + 1kedua sisi: 0 + 1 != x - 1 + 11 != x.
Bagaimana Anda mengatasi 0 != x ^ 1untuk x? Anda di ^ 1kedua sisi: 0 ^ 1 != x ^ 1 ^ 11 != x.

pengguna541686
sumber
6

Saya kira ada bit lain atau nilai bit-field x, dan ini dimaksudkan untuk menguji bahwa hanya bit orde rendah yang ditetapkan. Dalam konteksnya, saya rasa ini adalah default, dan karena itu pengkodean ini dan beberapa yang terkait m(mungkin lebih mahal untuk dikodekan) dapat dilewati, karena keduanya harus merupakan nilai default, diinisialisasi dalam konstruktor atau serupa.

Entah bagaimana dekoder harus dapat menyimpulkan bahwa nilai-nilai ini hilang. Jika mereka berada di akhir suatu struktur, itu dapat dikomunikasikan melalui lengthnilai yang selalu ada.

Ed Staub
sumber
4

XOR berguna dalam flag C # enum. Untuk menghapus satu flag dari nilai enum, perlu menggunakan xor operator (referensi di sini )

Contoh:

[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
Igrek.
sumber
TAPI pertanyaannya adalah tentang C ++, bukan C #
theDmi
@theDmi: TETAPI JUGA tentang manipulasi bit dan bitmask. Flag enum di C # jelas tentang bitmask.
Igrek.
Plus itu bisa berguna di C ++ juga. Lihat: Stack 1 dan Stack 2
Igrek.
Jawaban ini tampaknya tidak ada hubungannya dengan pertanyaan awal, selain beberapa diskusi tentang operator XOR bitwise?
Paul R
4

Ada banyak jawaban bagus tapi saya suka memikirkannya dengan cara yang lebih sederhana.

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

Pertama-tama. Pernyataan if hanya salah jika argumennya nol. Ini berarti membandingkan tidak sama dengan nol adalah sia-sia.

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

Sehingga meninggalkan kita dengan:

if ( x ^ 0x1 );

XOR dengan satu. Apa yang dilakukan XOR pada dasarnya mendeteksi bit yang berbeda. Jadi, jika semua bit itu sama, ia akan mengembalikan 0. Karena 0 itu salah, satu-satunya waktu ia akan kembali palsu adalah jika semua bit itu sama. Jadi akan salah jika argumennya sama, benar jika berbeda ... sama seperti tidak sama dengan operator.

if ( x != 0x1 );

Jika faktanya, satu-satunya perbedaan antara keduanya adalah yang !=akan mengembalikan 0 atau 1, sementara ^akan mengembalikan nomor berapa pun, tetapi kebenaran dari hasilnya akan selalu sama. Cara mudah untuk memikirkannya adalah.

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

"Penyederhanaan" akhir diubah 0x1menjadi desimal yaitu 1. Oleh karena itu pernyataan Anda setara dengan:

if ( x != 1 )
Kevin Cox
sumber
1

^ adalah operator XOR bitwise

Jika x = 1

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

di sini 0 == (x ^ 0x1)

Jika x = 0

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

di sini 0! = (x ^ 0x1)

Tabel kebenaran a xor b:

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

Kode itu hanya berarti

akbar ali
sumber
6
Apakah benar-benar perlu mengirim jawaban duplikat lain?
Mysticial
2
Anda bisa mengatakan jawaban lain tetapi tidak duplikat. maaf jika Anda keberatan
akbar ali
1

Teknik standar yang mungkin digunakan, di sini, adalah mengulangi sebuah idiom seperti yang muncul dalam konteks sekitarnya untuk kejelasan, daripada mengaburkannya dengan menggantinya dengan idiom yang secara aritmetika lebih sederhana tetapi tidak bermakna secara kontekstual.

Kode di sekitarnya mungkin sering membuat referensi (x ^ 1), atau tes mungkin bertanya "jika bit 0 adalah sebaliknya, apakah bit-mask ini kosong?".

Mengingat bahwa kondisi menyebabkan sesuatu untuk encode()diedit, mungkin dalam konteks keadaan default bit 0 telah terbalik oleh faktor-faktor lain, dan kami hanya perlu menyandikan informasi tambahan jika ada bit yang menyimpang dari standarnya (biasanya semua-nol ).

Jika Anda mengeluarkan ungkapan di luar konteks dan bertanya apa fungsinya, Anda mengabaikan niat yang mendasarinya. Anda mungkin juga melihat output perakitan dari kompiler dan melihat bahwa itu hanya melakukan perbandingan kesetaraan langsung dengan 1.

sh1
sumber
0

Seperti yang saya lihat jawabannya sejauh ini melewatkan aturan sederhana untuk menangani XORs. Tanpa merinci apa ^dan 0xartinya (dan if, dan !=lain - lain), ekspresi 0 != (x^1)dapat dikerjakan ulang sebagai berikut dengan menggunakan fakta bahwa (a^a)==0:

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