下面的位运算符在现实世界中有哪些用例?
和 XOR 不 或 左/右转
下面的位运算符在现实世界中有哪些用例?
和 XOR 不 或 左/右转
当前回答
低级编程就是一个很好的例子。例如,你可能需要写一个特定的位到内存映射寄存器,以使某些硬件做你想要它做的事情:
volatile uint32_t *register = (volatile uint32_t *)0x87000000;
uint32_t value;
uint32_t set_bit = 0x00010000;
uint32_t clear_bit = 0x00001000;
value = *register; // get current value from the register
value = value & ~clear_bit; // clear a bit
value = value | set_bit; // set a bit
*register = value; // write it back to the register
同样,htonl()和htons()是使用&和|操作符实现的(在字节顺序不匹配网络顺序的机器上):
#define htons(a) ((((a) & 0xff00) >> 8) | \
(((a) & 0x00ff) << 8))
#define htonl(a) ((((a) & 0xff000000) >> 24) | \
(((a) & 0x00ff0000) >> 8) | \
(((a) & 0x0000ff00) << 8) | \
(((a) & 0x000000ff) << 24))
其他回答
加密都是按位操作。
一个常见的用法是对齐,例如我需要我的数据在4字节或16字节的边界上对齐。这在RISC处理器中非常常见,其中未对齐的加载/存储要么代价高昂(因为它触发了一个异常处理程序,然后需要修复未对齐的加载),要么根本不允许。
对于任何以2为幂的对齐,下一个对齐的pos可以计算如下:
aligned_offset = alignment + ((current_offset - 1) & ~(alignment - 1))
所以在4字节对齐和当前偏移量为9的情况下:
aligned_offset = 4 + ((9-1) & ~(4-1)) = 4 + (8 & 0xFFFFFFFC) = 4+ 8 = 12
所以下一个4字节的对齐偏移量是12
在当今现代语言的抽象世界里,没有太多。File IO是一个容易想到的方法,尽管它是在已经实现的东西上执行按位操作,而不是实现使用按位操作的东西。尽管如此,作为一个简单的例子,这段代码演示了在c#中删除文件上的只读属性(这样它就可以与指定FileMode.Create的新FileStream一起使用):
//Hidden files posses some extra attibutes that make the FileStream throw an exception
//even with FileMode.Create (if exists -> overwrite) so delete it and don't worry about it!
if(File.Exists(targetName))
{
FileAttributes attributes = File.GetAttributes(targetName);
if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
File.SetAttributes(targetName, attributes & (~FileAttributes.ReadOnly));
File.Delete(targetName);
}
As far as custom implementations, here's a recent example: I created a "message center" for sending secure messages from one installation of our distributed application to another. Basically, it's analogous to email, complete with Inbox, Outbox, Sent, etc, but it also has guaranteed delivery with read receipts, so there are additional subfolders beyond "inbox" and "sent." What this amounted to was a requirement for me to define generically what's "in the inbox" or what's "in the sent folder". Of the sent folder, I need to know what's read and what's unread. Of what's unread, I need to know what's received and what's not received. I use this information to build a dynamic where clause which filters a local datasource and displays the appropriate information.
下面是枚举是如何组合在一起的:
public enum MemoView :int
{
InboundMemos = 1, // 0000 0001
InboundMemosForMyOrders = 3, // 0000 0011
SentMemosAll = 16, // 0001 0000
SentMemosNotReceived = 48, // 0011
SentMemosReceivedNotRead = 80, // 0101
SentMemosRead = 144, // 1001
Outbox = 272, //0001 0001 0000
OutBoxErrors = 784 //0011 0001 0000
}
你明白这是怎么回事了吗?通过与“收件箱”枚举值InboundMemos加上(&),我知道InboundMemosForMyOrders在收件箱中。
下面是该方法的简化版本,它构建并返回为当前选择的文件夹定义视图的过滤器:
private string GetFilterForView(MemoView view, DefaultableBoolean readOnly)
{
string filter = string.Empty;
if((view & MemoView.InboundMemos) == MemoView.InboundMemos)
{
filter = "<inbox filter conditions>";
if((view & MemoView.InboundMemosForMyOrders) == MemoView.InboundMemosForMyOrders)
{
filter += "<my memo filter conditions>";
}
}
else if((view & MemoView.SentMemosAll) == MemoView.SentMemosAll)
{
//all sent items have originating system = to local
filter = "<memos leaving current system>";
if((view & MemoView.Outbox) == MemoView.Outbox)
{
...
}
else
{
//sent sub folders
filter += "<all sent items>";
if((view & MemoView.SentMemosNotReceived) == MemoView.SentMemosNotReceived)
{
if((view & MemoView.SentMemosReceivedNotRead) == MemoView.SentMemosReceivedNotRead)
{
filter += "<not received and not read conditions>";
}
else
filter += "<received and not read conditions>";
}
}
}
return filter;
}
非常简单,但在抽象级别上是一个整洁的实现,通常不需要按位操作。
一个非常具体的例子,但我用它们让我的数独求解器运行得更快(我和一个朋友进行了比赛)
每一列、行和3x3都表示为一个无符号整数,当我设置数字时,我会为相关列、行和3x3平方中设置的数字标记适当的位。
这样就很容易看到我可以在给定的正方形中放置什么可能的数字,因为我将右边的列、行和3x3的正方形放在一起,然后不这样做,留下一个表示给定位置可能的合法值的掩码。
希望大家能理解。
下面是一些处理将标志存储为单个位的常见习惯用法。
enum CDRIndicators {
Local = 1 << 0,
External = 1 << 1,
CallerIDMissing = 1 << 2,
Chargeable = 1 << 3
};
unsigned int flags = 0;
设置Chargeable标志:
flags |= Chargeable;
清除CallerIDMissing标记:
flags &= ~CallerIDMissing;
测试CallerIDMissing和Chargeable是否设置:
if((flags & (CallerIDMissing | Chargeable )) == (CallerIDMissing | Chargeable)) {
}