例如:

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 ]

在这种情况下,我可以看到它有效,但我不确定逻辑是什么? 而且我不确定我是否可以从头开始创建自己的位操作。我如何开始以位为单位思考?

最佳答案


人们已经回答了你的第一个问题——解释逻辑。我希望向您展示一个非常基本的、冗长但标准的方法来进行任何有点麻烦的操作。 (注意,一旦你习惯了处理位,你就会开始思考 & 和 | ,而不会做这些废话)。

  • 弄清楚您希望您的操作做什么。
  • 写出 FULL 真值表。
  • 要么直接从表中读取乘积总和,要么制作卡诺图。 km将大大减少最终方程。
  • ???
  • 利润

  • 根据您给出的示例进行推导。即,掩码从 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/

    10-11 22:07
    查看更多