2017-04-17 136 views
-1
struct st 
{ 
    int a1 : 3; 
    int a2 : 2; 
    int a3 : 1; 
} 

void main(void) 
{ 
    x.a3 = -1; 

    if (x.a3 == -1) printf("TRUE\n"); 
    else printf("FALSE\n"); 

    x.a3 = 1; 
    if (x.a3 == 1) printf("TRUE\n"); 
    else printf("FALSE\n"); 
} 

如果'x.a3 = -1;'首先如果是TRUE
但是,爲什麼'x.a3 = 1'不會在第二個變化?它仍然是x.a3 = -1。結構變量未被賦值改變

and
如果我輸入'x.a3 = 1;'在第一個如果,它仍然x.a3 = = 1!它並沒有改變!

Debug Result in XCode

+0

'void main()'是一個無效的簽名。最小簽名是'int main(void)'。什麼是'x'?代碼不能編譯。提供[mcve]。 – Olaf

+0

@Olaf在閱讀C11 5.1.2.2.1 2時,「它應該用int的返回類型或其他實現定義的方式來定義。」 'void main(void)'是實現定義的,如果它是有效的,當然不是無效的。我想這取決於「或」。 IAC,當然不是OP的關鍵問題。 – chux

+0

@chux:這是受解釋。除此之外,所有的全尺寸操作系統都需要一個「int」結果。 – Olaf

回答

3

的問題是,一個簽署1位變量只能容納兩個值,-10(閱讀Two's complement)。僅保留1(準確地說+ 1)是不夠的。

爲了詳細描述,而寫分配

x.a3 = 1; 

整數的常數1的值被存儲到用於構件a3保留的存儲器位置,但在訪問變量,按照變量的符號性(可能是signedunsigned,按照章節§6.7.2/ P5的實現定義的行爲),表示將從內存中讀取。

在二的補一存儲值的1的表示,將產生的結果-1(根據MSB值),所以與== 1條件檢查會失敗,始終。

+1

它是實現定義是否在位字段中的純'int'是一個有符號或無符號的值。事實上,幾乎所有關於位域的內容都是實現定義的。 –

+0

@chux感謝您糾正我,我錯過了之前的評論。更新。 –

0

由於字段a3是1位int(因此是帶符號的),它只能保存0(如果該位爲0)或-1(如果該位是符號位爲1) 。因此,當您嘗試分配值1時,將存儲該值的表示形式,並且該給定數據類型中的表示形式爲-1。

僅僅因爲1位int中的值-1與1位unsigned int中的值1具有相同的表示,並不意味着它們與相同的事情相比較。

0
int a3 : 1; 

是一個帶位字段的結構,它定義了要使用多少空間來存儲var。您正在使a1成爲一個帶符號的int整數,它只能保存值-1和0.如果您希望a3保存值1,那麼您可能希望的語法是int a3 = 1,然後是多種方法之一這樣做可能看起來像這樣

struct st 
{ 
    int a1 : 3; 
    int a2 : 2; 
    int a3 : 1; 
}; 


void main(void) 
{ 
    struct st x = {1,2,3}; 
    x.a3 = -1; 

    if (x.a3 == -1) printf("TRUE\n"); 
    else printf("FALSE\n"); 

    x.a3 = 1; 
    if (x.a3 == 1) printf("TRUE\n"); 
    else printf("FALSE\n"); 
}