2015-10-15 52 views
2

比方說,我有以下最好的方式來設置字段位工會

struct S { 
union { 
    uint8_t flags; 
    struct { 
     uint8_t flag2bits : 2; 
     uint8_t flag1bit : 1; 
    }; 
}; 
}; 

S s; 
s.flag2bits = 2; 
s.flag1bit = 1; // this will wipe out the values of other bits 

什麼是值分配給特定的位,但不影響其他位域的最佳途徑?

我可以遊移,然後分配,然後再做出調整,但它意味着一旦有人改變位字段的順序,代碼被打破....

+1

寫入一個位域不會與其他位混淆,這會使位域絕對無用 - http://coliru.stacked-crooked.com/a/3bbf315576887706 – Praetorian

+0

@Praetorian除非有多個線程。 –

+1

@AlanStokes有關C++行爲的每個聲明隱含地具有「除非存在未定義的行爲」 –

回答

4

我可以遊移,然後分配,然後再做出調整,但它意味着 一旦有人改變位字段的順序,代碼 破....

不,這不是代表代碼被破壞了。你可以改變任何(以任意順序/你可以把其中的一些未設置),你喜歡

在您的示例位字段:

S s; 
s.flag2bits = 2; 
s.flag1bit = 1; 

更改flag2bits不會影響存儲在flag1bit值。

但是,您的問題可能與您在struct中持有的union有關。更改flags變量影響這兩個位域,因爲您將它們存儲在單獨的struct中。

我希望這個例子解釋這裏的情況:

#include <iostream> 
#include <cstdint> 
struct S { 
    union { 
     uint8_t flags; 
     struct { 
      uint8_t flag2bits : 2; 
      uint8_t flag1bit : 1; 
     }; 
    }; 
}; 

int main(int argc, char *argv[]) { 
    S s; 
    s.flag2bits = 2; 
    s.flag1bit = 1; 

    std::cout << int(s.flag2bits) << int(s.flag1bit) << std::endl; 
    s.flags = 4; // As you are using union, at this point you are overwriting 
        // values stored in your (nested) struct 
    std::cout << int(s.flag2bits) << int(s.flag1bit) << std::endl; 

    return 0; 
} 

編輯:作爲@ M.M指出,it's undefined behavior to read from the member of the union that wasn't most recently written。雖然至少在鏗鏘-3.5,上面的代碼將打印:

21 
01 

這說明我試圖讓點(即工會領域的覆蓋)。

我會考慮從您的struct S代碼中刪除union,儘管我可能沒有看到您想要實現的全貌。

+0

在編寫's.flags'後讀取's.flag2bits'會導致未定義的行爲:在C++中,只能讀取最近寫入的聯合成員 –

+0

@MM謝謝,我已經添加到我的答案。 – syntagma

+0

@ M.M新對我來說。那麼這是否意味着如果我寫入s.flag2bits然後s.flag1bit,那麼讀取s.flag2bits的行爲是不確定的?或者,那麼從s.flags讀取的行爲是不確定的?只是想明白。謝謝! – Hei

1

C++編譯器將負責管理該位爲您服務。您可以按照您的設置來設置值。只有適當的位將被設置。

你嘗試了嗎?