c# - 位运算的实际应用

标签 c# bitwise-operators

<分区>

  1. 您使用位运算做什么?
  2. 为什么它们这么方便?
  3. 有人可以推荐一个非常简单的教程吗?

最佳答案

虽然每个人似乎都对标志用例着迷,但这并不是按位运算符的唯一应用(尽管可能是最常见的)。此外,C# 是一种足够高级的语言,其他技术可能很少使用,但仍然值得了解它们。这是我能想到的:


<<>>运算符可以快速乘以 2 的幂。当然,.NET JIT 优化器可能会为您执行此操作(以及其他语言的任何体面的编译器),但如果您真的担心每一微秒,您可能会写这个是为了确定。

这些运算符的另一个常见用途是将两个 16 位整数填充到一个 32 位整数中。喜欢:

int Result = (shortIntA << 16 ) | shortIntB;

这对于与 Win32 函数的直接接口(interface)很常见,有时出于遗留原因使用此技巧。

当然,当您想让没有经验的人感到困惑时,例如在提供家庭作业问题的答案时,这些运算符很有用。 :)

尽管在任何实际代码中使用乘法会好得多,因为它具有更好的可读性并且 JIT 将其优化为 shlshr说明,所以没有性能损失。


处理 ^ 的一些奇怪的技巧运算符(异或)。这实际上是一个非常强大的运算符,因为它具有以下特性:

  • A^B == B^A
  • A^B^A == B
  • 如果你知道A^B那么就不可能说出什么AB是,但如果您知道其中之一,则可以计算出另一个。
  • 运算符不会出现任何溢出,例如乘法/除法/加法/减法。

我看到的一些使用此运算符的技巧:

在没有中间变量的情况下交换两个整数变量:

A = A^B // A is now XOR of A and B
B = A^B // B is now the original A
A = A^B // A is now the original B

双向链表,每一项只有一个额外的变量。这在 C# 中用处不大,但对于每个字节都很重要的嵌入式系统的低级编程可能会派上用场。

这个想法是您跟踪第一个项目的指针;最后一项的指针;对于每件商品,您都会跟踪 pointer_to_previous ^ pointer_to_next .这样你就可以从任一端遍历列表,而开销只是传统链表的一半。这是用于遍历的 C++ 代码:

ItemStruct *CurrentItem = FirstItem, *PreviousItem=NULL;
while (  CurrentItem != NULL )
{
    // Work with CurrentItem->Data

    ItemStruct *NextItem = CurrentItem->XorPointers ^ PreviousItem;
    PreviousItem = CurrentItem;
    CurrentItem = NextItem;
}

要从末尾开始遍历,您只需将第一行从 FirstItem 更改为至 LastItem .这是另一个内存节省。

我使用 ^ 的另一个地方C# 中的定期运算符是当我必须为我的复合类型的类型计算 HashCode 时。喜欢:

class Person
{
    string FirstName;
    string LastName;
    int Age;

    public int override GetHashCode()
    {
        return (FirstName == null ? 0 : FirstName.GetHashCode()) ^
            (LastName == null ? 0 : LastName.GetHashCode()) ^
            Age.GetHashCode();
    }
}

关于c# - 位运算的实际应用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3883384/

相关文章:

javascript - "MVC"和 "Single Page Application"模板有什么区别?

c# - Prism EventAggregator 订阅执行两次

c - c中的移位乘法不使用2的幂

python - 位运算和 == 与 != 运算符

javascript ->> 按位运算符未按预期工作

assembly - 浮点按位运算的用处

c# - 错误 - 与当前连接关联的事务已完成但尚未处理

c# - 如何使 Roslyn Compilation 复制引用

c# - 返回 IQueryable<T> 或不返回 IQueryable<T>

Javascript - 解析十六进制值