位运算符 #

一、位运算符概述 #

C#提供了以下位运算符:

运算符 名称 说明
& 按位与 两位都为1时结果为1
| 按位或 至少一位为1时结果为1
^ 按位异或 两位不同时结果为1
~ 按位取反 0变1,1变0
<< 左移 各位左移若干位
>> 右移 各位右移若干位
>>> 无符号右移 无符号右移(C# 11+)

二、按位与运算 #

2.1 基本用法 #

csharp
int a = 12;
int b = 10;
int result = a & b;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(8, '0')}");
Console.WriteLine($"{b} = {Convert.ToString(b, 2).PadLeft(8, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(8, '0')}");

运算过程:

text
  00001100  (12)
& 00001010  (10)
----------
  00001000  (8)

2.2 应用场景 #

掩码操作:

csharp
int flags = 0b1101;
int mask = 0b0100;
bool hasFlag = (flags & mask) != 0;

int clearBit = flags & ~mask;

提取位:

csharp
int value = 0b10110110;
int lowNibble = value & 0x0F;
int highNibble = (value >> 4) & 0x0F;

判断奇偶:

csharp
bool isOdd = (number & 1) == 1;
bool isEven = (number & 1) == 0;

三、按位或运算 #

3.1 基本用法 #

csharp
int a = 12;
int b = 10;
int result = a | b;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(8, '0')}");
Console.WriteLine($"{b} = {Convert.ToString(b, 2).PadLeft(8, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(8, '0')}");

运算过程:

text
  00001100  (12)
| 00001010  (10)
----------
  00001110  (14)

3.2 应用场景 #

设置标志位:

csharp
[Flags]
public enum Permissions
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4,
    All = Read | Write | Execute
}

Permissions userPerms = Permissions.Read | Permissions.Write;

合并值:

csharp
byte red = 255;
byte green = 128;
byte blue = 64;

int rgb = (red << 16) | (green << 8) | blue;

四、按位异或运算 #

4.1 基本用法 #

csharp
int a = 12;
int b = 10;
int result = a ^ b;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(8, '0')}");
Console.WriteLine($"{b} = {Convert.ToString(b, 2).PadLeft(8, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(8, '0')}");

运算过程:

text
  00001100  (12)
^ 00001010  (10)
----------
  00000110  (6)

4.2 应用场景 #

交换两个数:

csharp
int a = 10;
int b = 20;

a = a ^ b;
b = a ^ b;
a = a ^ b;

Console.WriteLine($"a = {a}, b = {b}");

简单加密:

csharp
string message = "Hello";
int key = 42;

string encrypted = new string(message.Select(c => (char)(c ^ key)).ToArray());
string decrypted = new string(encrypted.Select(c => (char)(c ^ key)).ToArray());

切换位:

csharp
int flags = 0b1010;
int toggleMask = 0b0100;
flags = flags ^ toggleMask;

五、按位取反运算 #

5.1 基本用法 #

csharp
int a = 12;
int result = ~a;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(32, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(32, '0')}");

运算过程:

text
~ 00000000000000000000000000001100  (12)
-----------------------------------
  11111111111111111111111111110011  (-13)

5.2 应用场景 #

清除位:

csharp
int value = 0b1111;
int mask = 0b0010;
int result = value & ~mask;

六、移位运算 #

6.1 左移运算 << #

csharp
int a = 5;
int result = a << 2;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(8, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(8, '0')}");

运算过程:

text
00000101  (5)
    <<
00010100  (20)

快速乘法:

csharp
int a = 5;
int multiplied = a << 1;
int multiplied4 = a << 2;
int multiplied8 = a << 3;

6.2 右移运算 >> #

csharp
int a = 20;
int result = a >> 2;

Console.WriteLine($"{a} = {Convert.ToString(a, 2).PadLeft(8, '0')}");
Console.WriteLine($"{result} = {Convert.ToString(result, 2).PadLeft(8, '0')}");

运算过程:

text
00010100  (20)
    >>
00000101  (5)

快速除法:

csharp
int a = 20;
int divided = a >> 1;
int divided4 = a >> 2;
int divided8 = a >> 3;

算术右移(保留符号位):

csharp
int negative = -20;
int result = negative >> 2;

6.3 无符号右移 >>>(C# 11+) #

csharp
int negative = -20;
int result = negative >>> 2;

七、位标志枚举 #

7.1 定义标志枚举 #

csharp
[Flags]
public enum FileAccess
{
    None = 0,
    Read = 1,
    Write = 2,
    ReadWrite = Read | Write,
    Delete = 4,
    All = Read | Write | Delete
}

7.2 使用标志枚举 #

csharp
FileAccess access = FileAccess.Read | FileAccess.Write;

bool canRead = access.HasFlag(FileAccess.Read);
bool canDelete = (access & FileAccess.Delete) == FileAccess.Delete;

access |= FileAccess.Delete;
access &= ~FileAccess.Write;

access ^= FileAccess.Read;

八、实战示例 #

8.1 颜色处理 #

csharp
public struct Color
{
    public byte A { get; set; }
    public byte R { get; set; }
    public byte G { get; set; }
    public byte B { get; set; }
    
    public int ToArgb()
    {
        return (A << 24) | (R << 16) | (G << 8) | B;
    }
    
    public static Color FromArgb(int argb)
    {
        return new Color
        {
            A = (byte)((argb >> 24) & 0xFF),
            R = (byte)((argb >> 16) & 0xFF),
            G = (byte)((argb >> 8) & 0xFF),
            B = (byte)(argb & 0xFF)
        };
    }
}

8.2 位图操作 #

csharp
public class BitArray
{
    private int[] _data;
    
    public BitArray(int size)
    {
        _data = new int[(size + 31) / 32];
    }
    
    public bool this[int index]
    {
        get => (_data[index / 32] & (1 << (index % 32))) != 0;
        set
        {
            if (value)
                _data[index / 32] |= 1 << (index % 32);
            else
                _data[index / 32] &= ~(1 << (index % 32));
        }
    }
}

8.3 权限管理 #

csharp
[Flags]
public enum Permission
{
    None = 0,
    Create = 1,
    Read = 2,
    Update = 4,
    Delete = 8,
    All = Create | Read | Update | Delete
}

public class User
{
    public Permission Permissions { get; set; }
    
    public bool Can(Permission permission)
    {
        return Permissions.HasFlag(permission);
    }
    
    public void Grant(Permission permission)
    {
        Permissions |= permission;
    }
    
    public void Revoke(Permission permission)
    {
        Permissions &= ~permission;
    }
}

九、位运算技巧 #

9.1 判断2的幂 #

csharp
bool IsPowerOfTwo(int n)
{
    return n > 0 && (n & (n - 1)) == 0;
}

9.2 计算绝对值 #

csharp
int Abs(int n)
{
    int mask = n >> 31;
    return (n + mask) ^ mask;
}

9.3 交换符号 #

csharp
int Negate(int n)
{
    return ~n + 1;
}

9.4 计算位数 #

csharp
int CountBits(int n)
{
    int count = 0;
    while (n != 0)
    {
        count += n & 1;
        n >>= 1;
    }
    return count;
}

十、总结 #

位运算符要点:

运算符 说明
& 按位与
| 按位或
^ 按位异或
~ 按位取反
<< 左移
>> 右移

下一步,让我们学习赋值运算符!

最后更新:2026-03-26