簡體   English   中英

我可以設置一個位序列而不重置先前的值嗎?

[英]Can I set a sequence of bits without unsetting the previous values?

我說了一些話

0110 [1011] 1111

假設我要將myddle nybble設置為0111作為新值。

使用與ANDOR的位置屏蔽方法,我似乎別無選擇,只能先將原始值取消設置為0000 ,因為如果我嘗試對原始值1011 AND ing或OR ing,則我不會預期結果為0111

我應該使用另一個邏輯運算符來獲得所需的效果嗎? 還是我每次都被鎖定兩次操作?


經過善意的協助,結果是:

inline void foo(Clazz* parent, const Uint8& material, const bool& x, const bool& y, const bool& z)
{
    Uint8 offset = x | (y << 1) | (z << 2); //(0-7)
    Uint64 positionMask = 255 << offset * 8; //255 = length of each entry (8 bits), 8 = number of bits per material entry
    Uint64 value = material << offset * 8;
    parent->childType &= ~positionMask; //flip bits to clear given range.
    parent->childType |= value;
}

...我相信這會得到進一步的改進,但這是(半)可讀版本。

如果您碰巧已經知道這些位的當前值,則可以進行XOR:

  0110 1011 1111
^ 0000 1100 0000

= 0110 0111 1111

(其中1100需要計算為當前位與所需位之間的XOR)。

當然,這仍然是2個操作。 區別在於您可以在某些情況下預先計算第一個XOR。

除了這種特殊情況,沒有其他方法。 從根本上講,您需要表示3種狀態:設置為1,設置為0,不要更改。 您不能使用單個二進制操作數來執行此操作。

您可能需要使用位字段(如果希望能夠同時作為一組位字段和int來訪問結構,則可能要使用並集),類似於:

struct foo
{  
unsigned int o1:4;  
unsigned int o2:4;  
unsigned int o3:4;   
};  

foo bar;  

bar.o2 = 0b0111; 

不知道它是否比您的清除/設置轉換成更有效的機器代碼...

嗯,MMIX中有一個匯編指令:

SETL $1, 0x06BF ; 0110 1011 1111
SETL $2, 0x0070 ; 0000 0111 0000
SETL rM, 0x00F0 ; set mask register

MUX $1,$2,$1 ; result is 0110 0111 1111

但是在C ++中,您可能會想這就是“重置先前的值”。

int S = 0x6BF;      // starting value:   0110 1011 1111
int M = 0x0F0;      // value mask:       0000 1111 0000
int V = 0x070;      // value:            0000 0111 0000

int N = (S&~M) | V; // new value:        0110 0111 1111

但是由於(S&~M) 〜M)的中間結果0110 0000 1111從未存儲在任何位置的變量中,所以我不會真正將其稱為“未設置”。 這只是一個按位的布爾表達式。 具有相同真值表的任何布爾表達式都可以使用。 這是另一個:

N = ((S^V) & M) ^ A; // corresponds to Oli Charlesworth's answer

相關的真值表:

    S M V  (S& ~M) | V      ((S^V) & M) ^ S
    0 0 0    0 1   0           0   0    0
 *  0 0 1    0 1   1           1   0    0
    0 1 0    0 0   0           0   0    0
    0 1 1    0 0   1           1   1    1
    1 0 0    1 1   1           1   0    1
 *  1 0 1    1 1   1           0   0    1
    1 1 0    0 0   0           1   1    0
    1 1 1    0 0   1           0   0    1
                   ^                    ^
                   |____________________|

標有“ *”的行無所謂,因為它們不會發生(當未設置相應的掩碼位時,V中的位將永遠不會被設置)。 除了那些行外,表達式的真值表是相同的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM