Operator bitwise dan shift (referensi C#)

Operator bitwise dan shift mencakup pelengkap bitwise tidak biasa, shift kiri dan kanan biner, shift kanan yang tidak ditandatangani, dan logis biner AND, OR, dan operator OR eksklusif. Operan ini mengambil operand dari jenis numerik integral atau jenis karakter.

Operator tersebut didefinisikan untuk jenis int, uint, long, dan ulong. Ketika kedua operand adalah dari jenis integral lainnya (sbyte, byte, shortushort, atau char), nilainya dikonversi ke jenis int, yang juga merupakan jenis hasil operasi. Ketika operan dari jenis integral yang berbeda, nilainya dikonversi ke terdekat yang berisi jenis integral. Untuk informasi selengkapnya, lihat bagian Promosi numerik dari spesifikasi bahasa C#. Operator majemuk (seperti >>=) tidak mengonversi argumen mereka menjadi int atau memiliki jenis hasil int.

Operator &, |, dan ^ juga didefinisikan untuk operand jenis bool. Untuk informasi selengkapnya, lihat Konversi jenis boolean.

Operasi bitwise dan shift tidak menyebabkan luapan dan menghasilkan hasil yang sama dalam konteks dicentang dan tidak dicentang.

Operator pelengkap bitwise

Operator ~ menghasilkan pelengkap bitwise dari operannya dengan membalikkan setiap bit:

uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Console.WriteLine(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011

Anda juga dapat menggunakan simbol ~ untuk mendeklarasikan penutup. Untuk informasi selengkapnya, lihat Penutup.

Operator shift kiri <<

Operator << menggeser operand sebelah kirinya ke kiri dengan jumlah bit yang ditentukan oleh operand kanannya. Untuk informasi tentang pengoperasian sebelah kanan menentukan jumlah shift, lihat jumlah Shift dari bagian operator shift.

Operasi shift kiri membuang bit urutan tinggi yang berada di luar rentang jenis hasil, dan mengatur posisi bit kosong berurutan rendah ke nol, seperti ditunjukkan contoh berikut:

uint x = 0b_1100_1001_0000_0000_0000_0000_0001_0001;
Console.WriteLine($"Before: {Convert.ToString(x, toBase: 2)}");

uint y = x << 4;
Console.WriteLine($"After:  {Convert.ToString(y, toBase: 2)}");
// Output:
// Before: 11001001000000000000000000010001
// After:  10010000000000000000000100010000

Karena operator shift didefinisikan hanya untuk jenis int, uint, long, dan ulong, hasil operasi selalu berisi minimal 32 bit. Jika operand sebelah kiri adalah jenis integral lain (sbyte, byte, short, ushort, atau char), nilainya dikonversi ke jenis int, seperti ditunjukkan contoh berikut:

byte a = 0b_1111_0001;

var b = a << 8;
Console.WriteLine(b.GetType());
Console.WriteLine($"Shifted byte: {Convert.ToString(b, toBase: 2)}");
// Output:
// System.Int32
// Shifted byte: 1111000100000000

Operator shift kanan >>

Operator >> menggeser operand sebelah kirinya ke kiri dengan jumlah bit yang ditentukan oleh operand kanannya. Untuk informasi tentang pengoperasian sebelah kanan menentukan jumlah shift, lihat jumlah Shift dari bagian operator shift.

Operasi shift kanan membuang bit berurutan rendah, seperti ditunjukkan contoh berikut:

uint x = 0b_1001;
Console.WriteLine($"Before: {Convert.ToString(x, toBase: 2), 4}");

uint y = x >> 2;
Console.WriteLine($"After:  {Convert.ToString(y, toBase: 2).PadLeft(4, '0'), 4}");
// Output:
// Before: 1001
// After:  0010

Posisi bit kosong berurutan tinggi diatur berdasarkan jenis operand sebelah kiri sebagai berikut:

  • Jika operand sebelah kiri berjenis int atau long, operator shift kanan melakukan pergeseran aritmatika : nilai bit yang paling signifikan (bit tanda) dari operand sebelah kiri disebarkan ke posisi bit kosong urutan tinggi. Artinya, posisi bit kosong urutan tinggi diatur ke nol jika operand sebelah kiri tidak negatif dan diatur ke satu jika negatif.

    int a = int.MinValue;
    Console.WriteLine($"Before: {Convert.ToString(a, toBase: 2)}");
    
    int b = a >> 3;
    Console.WriteLine($"After:  {Convert.ToString(b, toBase: 2)}");
    // Output:
    // Before: 10000000000000000000000000000000
    // After:  11110000000000000000000000000000
    
  • Jika operand sebelah kiri berjenis uint atau ulong, operator shift kanan melakukan shift logis: posisi bit kosong urutan tinggi selalu diatur ke nol.

    uint c = 0b_1000_0000_0000_0000_0000_0000_0000_0000;
    Console.WriteLine($"Before: {Convert.ToString(c, toBase: 2), 32}");
    
    uint d = c >> 3;
    Console.WriteLine($"After:  {Convert.ToString(d, toBase: 2).PadLeft(32, '0'), 32}");
    // Output:
    // Before: 10000000000000000000000000000000
    // After:  00010000000000000000000000000000
    

Catatan

Gunakan operator shift kanan yang tidak ditandatangani untuk melakukan pergeseran logis pada operan jenis bilangan bulat yang ditandatangani. Ini lebih disukai untuk mentransmisikan operand sebelah kiri ke jenis yang tidak ditandatangani dan kemudian mentransmisikan hasil operasi shift kembali ke jenis yang ditandatangani.

Operator shift kanan yang tidak ditandatangani >>>

Tersedia di C# 11 dan yang lebih baru, >>> operator menggeser operand kirinya ke kanan dengan jumlah bit yang ditentukan oleh operand tangan kanannya. Untuk informasi tentang pengoperasian sebelah kanan menentukan jumlah shift, lihat jumlah Shift dari bagian operator shift.

Operator >>> selalu melakukan pergeseran logis . Artinya, posisi bit kosong berurutan tinggi selalu diatur ke nol, terlepas dari jenis operand sebelah kiri. Operator >> melakukan pergeseran aritmatika (yaitu, nilai bit yang paling signifikan disebarkan ke posisi bit kosong urutan tinggi) jika operand sebelah kiri adalah jenis yang ditandatangani. Contoh berikut menunjukkan perbedaan antara >> operator dan >>> untuk operand kiri negatif:

int x = -8;
Console.WriteLine($"Before:    {x,11}, hex: {x,8:x}, binary: {Convert.ToString(x, toBase: 2), 32}");

int y = x >> 2;
Console.WriteLine($"After  >>: {y,11}, hex: {y,8:x}, binary: {Convert.ToString(y, toBase: 2), 32}");

int z = x >>> 2;
Console.WriteLine($"After >>>: {z,11}, hex: {z,8:x}, binary: {Convert.ToString(z, toBase: 2).PadLeft(32, '0'), 32}");
// Output:
// Before:             -8, hex: fffffff8, binary: 11111111111111111111111111111000
// After  >>:          -2, hex: fffffffe, binary: 11111111111111111111111111111110
// After >>>:  1073741822, hex: 3ffffffe, binary: 00111111111111111111111111111110

Operator LOGIS AND &

Operator & menghitung logis bitwise DAN dari operan integralnya:

uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000

Untuk operand bool, operator & menghitung AND logis dari operand. Operator & unary adalah alamat operator.

Operator OR eksklusif logis

Operator ^ menghitung OR eksklusif logis bitwise, juga dikenal sebagai XOR logis bitwise, dari operand integralnya:

uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 11100100

Untuk operand bool, operator ^ menghitung OR eksklusif logis dari operand.

Operator OR logis |

Operator | menghitung OR logis bitwise dari operand integralnya:

uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10110001

Untuk operand bool, operator | menghitung OR logis dari operand.

Penetapan campuran

Untuk op operator biner, ekspresi penetapan campuran dari formulir

x op= y

setara dengan:

x = x op y

kecuali x hanya dievaluasi sekali.

Contoh berikut menunjukkan penggunaan penetapan campuran dengan operator bitwise dan shift:

uint INITIAL_VALUE = 0b_1111_1000;

uint a = INITIAL_VALUE;
a &= 0b_1001_1101; 
Display(a);  // output: 10011000

a = INITIAL_VALUE;
a |= 0b_0011_0001; 
Display(a);  // output: 11111001

a = INITIAL_VALUE;
a ^= 0b_1000_0000;
Display(a);  // output: 01111000

a = INITIAL_VALUE;
a <<= 2;
Display(a);  // output: 1111100000

a = INITIAL_VALUE;
a >>= 4;
Display(a);  // output: 00001111

a = INITIAL_VALUE;
a >>>= 4;
Display(a);  // output: 00001111

void Display(uint x) => Console.WriteLine($"{Convert.ToString(x, toBase: 2).PadLeft(8, '0'), 8}");

Karena promosi numerik, hasil op operasi mungkin tidak secara implisit dapat dikonversi ke jenis T dari x. Dalam kasus seperti itu, jika op adalah operator yang telah ditentukan sebelumnya dan hasil operasi secara eksplisit dapat dikonversi ke jenis T dari x, ekspresi penetapan campuran formulir x op= y setara dengan x = (T)(x op y), kecuali x hanya dievaluasi sekali. Contoh berikut menunjukkan perilaku tersebut:

byte x = 0b_1111_0001;

int b = x << 8;
Console.WriteLine($"{Convert.ToString(b, toBase: 2)}");  // output: 1111000100000000

x <<= 8;
Console.WriteLine(x);  // output: 0

Prioritas operator

Daftar berikut mengurutkan operator bitwise dan shift mulai dari prioritas tertinggi ke terendah:

  • Operator pelengkap bitwise ~
  • Operator <<shift , >>, dan >>>
  • Operator AND logis &
  • Operator OR eksklusif logis ^
  • Operator OR logis |

Gunakan tanda kurung (), untuk mengubah urutan evaluasi yang diberlakukan oleh prioritas operator:

uint a = 0b_1101;
uint b = 0b_1001;
uint c = 0b_1010;

uint d1 = a | b & c;
Display(d1);  // output: 1101

uint d2 = (a | b) & c;
Display(d2);  // output: 1000

void Display(uint x) => Console.WriteLine($"{Convert.ToString(x, toBase: 2), 4}");

Untuk daftar lengkap operator C# yang diurutkan berdasarkan tingkat prioritas, lihat bagian Prioritas operator dari artikel operator C#.

Jumlah shift dari operator shift

Untuk operator shift bawaan , , >>dan , jenis operand tangan kanan harus int atau jenis yang memiliki konversi numerik implisit <<yang telah ditentukan sebelumnya ke int>>>.

x << countUntuk ekspresi , x >> count, dan x >>> count , jumlah shift aktual tergantung pada jenis x sebagai berikut:

  • Jika jenis x adalah int atau uint, jumlah shift ditentukan oleh lima bit urutan rendah dari operand kanan. Artinya, jumlah shift dihitung dari count & 0x1F (atau count & 0b_1_1111).

  • Jika jenis x adalah long atau ulong, jumlah shift ditentukan oleh lima bit urutan rendah dari operand kanan. Artinya, jumlah shift dihitung dari count & 0x3F (atau count & 0b_11_1111).

Contoh berikut menunjukkan perilaku tersebut:

int count1 = 0b_0000_0001;
int count2 = 0b_1110_0001;

int a = 0b_0001;
Console.WriteLine($"{a} << {count1} is {a << count1}; {a} << {count2} is {a << count2}");
// Output:
// 1 << 1 is 2; 1 << 225 is 2

int b = 0b_0100;
Console.WriteLine($"{b} >> {count1} is {b >> count1}; {b} >> {count2} is {b >> count2}");
// Output:
// 4 >> 1 is 2; 4 >> 225 is 2

int count = -31;
int c = 0b_0001;
Console.WriteLine($"{c} << {count} is {c << count}");
// Output:
// 1 << -31 is 2

Catatan

Seperti yang ditunjukkan oleh contoh sebelumnya, hasil dari operasi shift bisa tidak nol bahkan jika nilai operand kanan lebih besar dari jumlah bit di operand kiri.

Operator logika enumerasi

Operator ~, &, |, dan ^ juga didukung oleh jenis enumerasi apa pun. Untuk operand dengan jenis enumerasi yang sama, operasi logis dilakukan pada nilai yang sesuai dari jenis integral yang mendasar. Misalnya, untuk salah satu x dan y dari jenis enumerasi T dengan jenis Uyang mendasar, ekspresi x & y menghasilkan hasil yang sama dengan ekspresi (T)((U)x & (U)y).

Anda biasanya menggunakan operator logis bitwise dengan jenis enumerasi yang ditentukan dengan atribut Bendera. Untuk informasi selengkapnya, lihat bagian Jenis enumerasi sebagai bendera bit dari artikel Jenis enumerasi.

Kelebihan beban operator

Jenis yang ditentukan pengguna dapat membebani~operator , , <<>>, >>>, &, |dan ^ . JIka operator biner kelebihan beban, operator penetapan campuran yang sesuai juga secara implisit kelebihan beban. Jenis yang ditentukan pengguna tidak dapat secara eksplisit membebani operator penetapan majemuk.

Jika jenis T yang ditentukan pengguna membebani <<operator , , >>atau >>> , jenis operand sebelah kiri harus T. Dalam C# 10 dan yang lebih lama, jenis operand tangan kanan harus int; dimulai dengan C# 11, jenis operan tangan kanan operator shift yang kelebihan beban dapat berupa apa pun.

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat bagian berikut dari spesifikasi bahasa C#:

Lihat juga