C# 使用位运算符 我一直在学习C语言,并从C++中的老工作中找到了一些熟悉的地方。我从未理解在实际应用中使用位运算符的原因。我从来没有使用过它们,也从来没有理由使用它们。我一直在研究它们是如何工作的;下面的示例显示按位移位运算符。位运算符的意义是什么,它们的用途以及它们是如何工作的
也许我在按位逻辑中遗漏了什么C# 使用位运算符 我一直在学习C语言,并从C++中的老工作中找到了一些熟悉的地方。我从未理解在实际应用中使用位运算符的原因。我从来没有使用过它们,也从来没有理由使用它们。我一直在研究它们是如何工作的;下面的示例显示按位移位运算符。位运算符的意义是什么,它们的用途以及它们是如何工作的,c#,bit-manipulation,C#,Bit Manipulation,也许我在按位逻辑中遗漏了什么 byte bitComp = 15; // bitComp = 15 = 00001111b byte bresult = (byte) ~bitComp; // bresult = 240 = 11110000b 以下是~补码位运算符的示例: byte bitComp = 15; // bitComp = 15 = 00001111b byte bresult = (byte) ~bitComp; // bre
byte bitComp = 15; // bitComp = 15 = 00001111b
byte bresult = (byte) ~bitComp; // bresult = 240 = 11110000b
以下是~补码位运算符的示例:
byte bitComp = 15; // bitComp = 15 = 00001111b
byte bresult = (byte) ~bitComp; // bresult = 240 = 11110000b
一个典型的用途是操纵表示互斥“标志”的位 MSDN中的示例: 另请参见StackOverflow问题。另一个典型(但我认为不太常见)用法是将多个数字组合成一个大数字。例如windows RGB宏:
#define RGB(r, g ,b) ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16)))
定义RGB(r,g,b)((DWORD)((字节)(r);(字)(g)我在运动控制中工作(除其他外)与驱动器通信的方式通常是使用位序列。在内存位置x设置一个位模式以设置运动配置文件,在内存位置y设置一个启用位以启动运动,从位置z读取模式以获取移动状态,等等。移动越低,必须执行的位旋转越多 除了组合标志之外,位逻辑在UI代码中并不一定需要,但它仍然非常重要。例如,我维护了一个二进制序列化库,它需要处理各种复杂的位打包策略(例如,变长基128整数编码)。这是其中一种实现方式(实际上,这是一种更慢/更安全的版本-还有其他用于处理缓冲数据的变体,但它们更难遵循):
公共静态bool TryDecodeUInt32(流源,输出uint值)
{
如果(source==null)抛出新的ArgumentNullException(“source”);
int b=source.ReadByte();
if(b<0)
{
数值=0;
返回false;
}
如果((b&0x80)==0)
{
//单字节
值=(uint)b;
返回true;
}
int-shift=7;
值=(uint)(b和0x7F);
bool-keepGoing;
int i=0;
做
{
b=source.ReadByte();
如果(b<0)抛出新的EndOfStreamException();
i++;
keepGoing=(b&0x80)!=0;
值|=((uint)(b&0x7F))COM编程示例:
HRESULT是一个由32位整数组成的错误代码。高位是一个标志,指示代码是表示成功(0)还是失败(1)。接下来的15位是一个整数,表示错误的类型—ole自动化错误或win32错误或其他任何错误。低16位是实际的错误代码
当您想要从HRESULT中获取或获取信息时,能够四处移位是非常有用的
现在,您几乎总是希望抽象掉位旋转。最好有一个方法(或C中的宏)告诉您HRESULT是否失败,而不是在源代码中实际旋转(hr&0x8000000)!=0的位。让编译器内联它
有很多低层数据结构的例子,其中信息被塞进字中,需要通过逐位操作提取。我脑子里有三个主要用途:
1)在嵌入式应用程序中,经常需要访问内存映射寄存器,其中每个位意味着某些东西(例如ADC或串行寄存器中的更新位)。这与C++相比,更与C++有关。
登记器。
2) 校验和的计算,比如CRC。它们使用移位和掩码。在任何人说“使用标准库”之前,我已经多次遇到非标准校验和,必须从头开始实现
3) 当处理来自另一个平台的数据时,这些数据具有不同的位或字节顺序(或两者都有)从您正在执行代码的那一个。在对嵌入式系统进行软件测试、通过网络接收尚未转换为网络顺序的数据或处理来自数据捕获系统的批量数据时,尤其如此。请查看。如果您确实感兴趣,请阅读Danny Cohen的经典文章。a c两组示例:
- 通信堆栈:连接到通信堆栈层中的数据的报头可能包含字节,其中这些字节中的各个位表示某些内容,因此在处理这些字节之前必须对其进行屏蔽。类似地,在响应中组装报头时,需要设置或清除各个位
- 嵌入式软件:嵌入式微控制器可以有数十个或数百个硬件寄存器,其中单个位(或其集合)控制芯片内的不同功能,或指示硬件部分的状态
顺便说一下,在C和C++中,不推荐在可移植性很重要的地方使用BITFEAR,因为位字段中的位顺序是依赖于编译器的。将被设置或清除。
关于“它们如何工作”:按位操作是CPU支持的最低级别操作之一,事实上,有些按位操作,如NAND和NOR,是通用的-您完全可以用一组足够大的NAND门来构建任何操作。这似乎是学术性的,但如果您看看加法器是如何实现的在硬件中实现,这通常就是它们的基本含义
至于“要点”:当然,在许多高级应用程序中,位操作没有多大用处,但在系统的最低级别上,它们非常重要。我不知道,没有位操作很难编写的东西包括设备驱动程序,
#define RGB(r, g ,b) ((DWORD) (((BYTE) (r) | ((WORD) (g) << 8)) | (((DWORD) (BYTE) (b)) << 16)))
public static bool TryDecodeUInt32(Stream source, out uint value)
{
if (source == null) throw new ArgumentNullException("source");
int b = source.ReadByte();
if (b < 0)
{
value = 0;
return false;
}
if ((b & 0x80) == 0)
{
// single-byte
value = (uint) b;
return true;
}
int shift = 7;
value = (uint)(b & 0x7F);
bool keepGoing;
int i = 0;
do
{
b = source.ReadByte();
if (b < 0) throw new EndOfStreamException();
i++;
keepGoing = (b & 0x80) != 0;
value |= ((uint)(b & 0x7F)) << shift;
shift += 7;
} while (keepGoing && i < 4);
if (keepGoing && i == 4)
{
throw new OverflowException();
}
return true;
}
enum
{
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8,
Option5 = 16
};
enum
{
Option1 = 1<<0,
Option2 = 1<<1,
Option3 = 1<<2,
Option4 = 1<<3,
Option5 = 1<<4
};
int result = 5 * (int)Math.Pow(2, 7);
int result = 5 << 7;
int abs(const int input) {
int temp = A >> 31;
return ( input ^ A ) - A;
}
bool data[64] = {...};
uint64_t data = ...;
enum Flags
{
flag_selected = 1 << 0,
flag_hidden = 1 << 1,
flag_removed = 1 << 2,
flag_hovering = 1 << 3,
flag_minimized = 1 << 4,
...
};
uint8_t flags = flag_selected | flag_hovering;
// Check if the element is hidden or removed.
if (flags & (flag_hidden | flag_removed))
{
...
}
bool data[64];
bool all_set = true;
for (int j=0; j < 64; ++j)
{
if (!data[j])
{
all_set = false;
break;
}
}
if (all_set)
{
// Do something different when all booleans are set.
...
}
uint64_t data = ...;
if (data == 0xffffffffffffffff)
{
// Do something different when all bits are set.
...
}
int count = 0;
for (int j=0; j < 64; ++j)
count += data[j];
// do something with count
uint64_t data = ...;
const int count = __popcnt64(data);
// do something with count
x = pow(2, n);
x = 1 << n;
x = n % power_of_two;
x = n & (power_of_two - 1);