簡體   English   中英

鑄造時如何將連續的位域轉換為變量

[英]How consecutive bit-fields are converted to variable when casting

我想在某些結構中使用標志,可以這樣說:

struct {
    flag1:1;
    flag2:1;
    flag3:1;
    flag4:1;
}Flags;

標志3和4描述了我現在的目標項目的工作方式。 我想將標志轉換為數字以讀取在flag3和flag4中設置的內容。 我要做的是:

uint8_t mode;
mode = ( ((uint8_t)Flags.flag4 << 1) | (uint8_t)Flags.flag3) );

令我驚訝的是它如此工作:

如果flag4 == 1並且flag3 == 1'mode'為3

如果flag4 == 1且flag3 == 0,則“ mode”為2,依此類推。

我的問題是:為什么? 我希望它能起作用,但我不知道為什么。

我在Atollic工作,用於STM32代碼。

因為flag4和flag3將被解釋為二進制數中的數字。 flag4將是最重要的。

Flags.flag4 << 1會將flag4左移,因此,如果flag4為1,則結果為10。然后我們執行邏輯或使用flag3。 如果flag3為1,將產生11,即二進制3。

這里有一個小循環可能會解釋它。 假設我們在數組中有8個標志,即int flags[8] 現在我們要將它們壓縮到uint8_t flagfield 可以通過以下循環完成:

flagfield=0;
for(int i=0; i<8; i++)
    flagfield |= (uint8_t)(flags[i] << i);

現在, flagfield將包含所有標志。 如果願意,可以將其解釋為正整數。

flag4為1且flag3為1時, flag4 << 1為10(十進制2),因為向左移動1。 | 您添加不移位的flag3 ,因此您有11(十進制為3)。

flag3為0時,它執行相同的操作,但結果為10(十進制2),因為flag3為0。

讓我們分析一下代碼:

模式=((((uint8_t)Flags.flag4 << 1)|(uint8_t)Flags.flag3));

第一:

(uint8_t)Flags.flag4
(uint8_t)Flags.flag3

Flags.flag4和Flags.flag3被強制轉換為uint8_t。 這部分很重要。 雖然Flags.flag4和Flags.flag3只有一位,但將其轉換為完整的8位。

下一個:

((uint8_t)Flags.flag4 << 1)

這會將flag4的值向左移動1位。 x * 2相同。 記住演員表把它變成完整的8位。 因此,轉移不會溢出。 flag4只能為0或1,因此在移位后為0或2。

最后,將兩個值累加在一起。 根據flag3和flag4的值,得出的結果為0-3。

請注意另一種編寫方法,盡管要使用特定於體系結構/ ABI的方法

struct {
    uint8_t flag1:1;
    uint8_t flag2:1;
    union {
        struct {
            uint8_t flag3:1;
            uint8_t flag4:1;
        };
        uint8_t flag34:2;
    };
} Flags;

在體系結構/ ABI的調用約定中,標記3和標記4在內存中的順序是分開的,因此標記34不那么可移植。 您可能必須重新標記這些標志才能獲得最佳結果(最短/最快的匯編)。

mode = ( ((uint8_t)Flags.flag4 << 1) | (uint8_t)Flags.flag3) );

什么時候:

如果flag4 == 1並且flag3 == 0'mode'為2

說明:

Flags.flag4 == 1
1 << 1 == 2
2 | 0 == 2

如果flag4 == 1並且flag3 == 1'mode'為3

Flags.flag4 == 1
1 << 1 == 2
2 | 1 == 3

你需要一本好的初學者C書

暫無
暫無

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

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