2012-08-07 29 views
7

程序是:打印位類型爲整數?轉換過程如何?

typedef struct xp { 
     int a:2; 
     int b:2; 
     int c:1; 
} xp; 

int main(void) 
{ 
     xp x; 
     memset(&x, 0, sizeof(xp)); 

     x.a = 1; 
     x.b = 3; 
     x.c = 1; 

     printf("%d\n",x.a); 
     printf("%d\n",x.b); 
     printf("%d\n",x.c); 

     return 0; 
} 

我得到1-1-11,爲什麼呢? a,b和c如何存儲在x中? printf(「%d \ n」,x.a);執行?

+0

這是重複的;我知道我之前回答過這個問題。我會看看我是否可以追查下來。 – 2012-08-07 23:23:43

+0

直到Carl發現這個重複:因爲你的編譯器將這個位域解釋爲二進制補碼。 – 2012-08-07 23:25:57

+2

它實際上是實現定義的,無論它們是簽名還是未簽名。 – 2012-08-07 23:32:14

回答

5

您對位域使用了簽名類型,這意味着您已創建了多達兩個兩位有符號整數和一個一位有符號整數。

用於雙位帶符號整數(二的補碼)的可能值是:-2,-1,0和1:

用於一個位帶符號整數(二的補碼)的可能值是-1和0

通過存儲值是「不適合」,就像你在這行做了:

x.b = 3; 
x.c = 1; 

你會得到奇怪的行爲,你的存儲位模式不同的解釋時,讀。你可以通過做一些像類似的經歷:與8位char類型的機器上

char x = 58147; 

,該值將不適合,所以你訪問x時讀一些不同的東西回來。

+0

@ccsnailpp,它是-1,因爲它是二進制補碼。首位是1,所以這意味着它是一個負數。要翻譯成相應的正數,執行'〜x + 1'。在這種情況下,「〜11 + 1 = 00 + 1 = 1」。在二進制補碼中,全1位模式總是表示-1。 – 2012-08-07 23:50:05

+0

謝謝您的詳細解釋。 – 2012-08-08 00:07:24

2

int類型的位域是signed int類型或unsigned int類型。選擇是實現定義的。這是歷史原因。這是intsigned int可以不同的唯一上下文。

這在C標準(C99 draftC11 draft)第6.7.2指定,以下類型說明符的列表:

每個逗號分隔的多集的指定相同的類型,除了 那對於位字段,它是實現定義的, 說明符int是否指定與signed int相同的類型,或者是unsigned int指定的相同類型 。

解決方案是避免使用普通的int位字段;始終將其聲明爲signed intunsigned int。 (後者幾乎總是更有意義。)

相關問題