例如:
unsigned int a; // value to merge in non-masked bits
unsigned int b; // value to merge in masked bits
unsigned int mask; // 1 where bits from b should be selected; 0 where from a.
unsigned int r; // result of (a & ~mask) | (b & mask) goes here
r = a ^ ((a ^ b) & mask);
根据掩码合并来自两个值的位。
[取自 here ]
在这种情况下,我可以看到它有效,但我不确定逻辑是什么? 而且我不确定我是否可以从头开始创建自己的位操作。我如何开始以位为单位思考?
最佳答案
人们已经回答了你的第一个问题——解释逻辑。我希望向您展示一个非常基本的、冗长但标准的方法来进行任何有点麻烦的操作。 (注意,一旦你习惯了处理位,你就会开始思考 & 和 | ,而不会做这些废话)。
根据您给出的示例进行推导。即,掩码从 A 或 B 中选择位。(0 是 A,1 是 B)
该表适用于每个输入 1 位。我不会做多一点,因为我不想浪费我的时间 :) (为什么?2^(2bits * 3inputs) = 64 个案例 :( 2^(3bits * 3inputs) = 512 个案例 :(( )
但好消息是,在这种情况下,操作与位数无关,因此 1 位示例 100% 没问题。事实上它是我推荐的:)
| A | B | M || R |
============++====
| 0 | 0 | 0 || 0 |
| 0 | 0 | 1 || 0 |
| 0 | 1 | 0 || 0 |
| 0 | 1 | 1 || 1 |
| 1 | 0 | 0 || 1 |
| 1 | 0 | 1 || 0 |
| 1 | 1 | 0 || 1 |
| 1 | 1 | 1 || 1 |
希望你能看到这个真值表是如何工作的。如何从中得到表达式?两种方法:KMaps 和手动。让我们先亲手做,好吗? :)
查看 R 为真的点,我们看到:
| A | B | M || R |
============++====
| 0 | 1 | 1 || 1 |
| 1 | 0 | 0 || 1 |
| 1 | 1 | 0 || 1 |
| 1 | 1 | 1 || 1 |
由此我们可以得出一个表达式:R = (~A & B & M) |
( A & ~B & ~M) |
( A & B & ~M) |
( A & B & M) |
希望你能看到它是如何工作的:在每种情况下看到的完整表达式。完整的意思是你需要在那里不变量。让我们在python中尝试一下:
a = 0xAE #10101110b
b = 0x64 #01100011b
m = 0xF0 #11110000b
r = (~a & b & m) | ( a & ~b & ~m) | ( a & b & ~m) | ( a & b & m)
print hex(r)
输出:0x6E
这些数字来自 Abel 的例子。输出是 0x6E
,即 01101110b
。所以它奏效了!欢呼。 (ps,如果您愿意,可以从第一个表中导出 ~r 的表达式。仅考虑 r 为 0 的情况)。
您创建的这个表达式是一个 bool “乘积总和”,又名析取范式,尽管 DNF 确实是使用一阶谓词逻辑时使用的术语。这个表情也是相当的难看。让它更小在纸上是一件乏味的事情,如果你参加编译器或硬件类(class),你会在大学攻读 CS 学位时做 50 万次。 (强烈推荐 :))
因此,让我们对此进行一些 bool 代数魔术(不要尝试遵循此方法,这是浪费时间):
(~a & b & m) | ( a & ~b & ~m) | ( a & b & ~m) | ( a & b & m)
|= ((~a & b & m) | ( a & ~b & ~m)) | ( a & b & ~m) | ( a & b & m)
拿我做的第一个子条款来说:((~a & b & m) | ( a & ~b & ~m))
|= (~a | (a & ~b & ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= ((~a | a) & (a | ~b) &( a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= (T & (a | ~b) &( a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
|= ((a | ~b) & (a | ~m)) & (b | ( a & ~b & ~m)) & (m | ( a & ~b & ~m))
等等等等等等。这是非常乏味的一点,以防万一你没有猜到。所以只要在你的 choice 的网站上敲一下表达式,它就会告诉你r = (a & ~m) | (b & m)
欢呼!结果正确。请注意,它甚至可能会为您提供一个涉及 XOR 的表达式,但谁在乎呢?实际上,有些人会这样做,因为 and
s 和 or
s 的表达式是 4 个操作(1 or
,2 and
,1 neg
),而 r = a ^ ((a ^ b) & mask)
是 3(2 xor
,1 and
)。现在,你如何用 kmaps 来做呢?好吧,首先你需要知道如何制作它们,我会让你去做的。 :) 只是谷歌它。有可用的软件,但我认为最好手动完成——它更有趣,而且程序不允许你作弊。
欺骗?好吧,如果你有很多输入,通常最好像这样减少表格:
| A | B | M || R |
============++====
| X | X | 0 || A |
| X | X | 1 || B |
例如那个 64 个案例表?| A1| A0| B1| B0| M1| M0|| R1| R0|
========================++========
| X | X | X | X | 0 | 0 || A1| A0|
| X | X | X | X | 0 | 1 || A1| B0|
| X | X | X | X | 1 | 0 || B1| A0|
| X | X | X | X | 1 | 1 || B1| B0|
在这个例子中归结为 4 个案例:)(其中 X 是“不在乎”。)然后将该表放在您的 Kmap 中。再一次,让你做一个练习[即,我忘记了如何做这个]。
希望你现在可以推导出你自己的 bool 疯狂,给定一组输入和一组预期的输出。
玩得开心。
关于c - 简单操作如何考虑位操作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1692802/