2016-03-06 64 views
3

我一直在看這段代碼。我知道輸出是50,但我不確定這是怎麼發生的。不確定輸出是如何得到的!位字段

struct 
{ 
    unsigned m : 3; 
    unsigned n : 5; 
} b; 

int main(void) 
{ 
    b.m = 2; 
    b.n = 6; 

    printf("%d", b); 
} 

任何幫助別人可以提供,我真的很感激。

+1

這調用**未定義的行爲** - 任何事情都可能發生。 –

+0

那就是我在想什麼。這是一個考試的練習題,我明顯應該做些什麼。我只能回答輸出 – guy25

+0

好的,但要記住練習文件是錯誤的,然後(除非預期的答案是「未定義的行爲」......) –

回答

1

嗯,似乎與位域連續的一個結構被壓縮,而傳遞給printf%d格式說明時,這體現像是某種「位聚合」(見注)。一些測試與不同的價值觀和這樣的,我想出了以下方案:

的結構成員(位域)的排列正是如此:

 
n n n n n m m m 

即「降」命令 - 去年是第一位的。

然後,在mainBM得到值2,其在二進制是10和在3位格式是010,和BN得到值6,其在二進制爲110,並在5位格式是00110,所以你最終00110010具有的價值十二月50.


爲了進一步檢驗這個假設我擴大了與一個成員的b結構,並檢查它是否仍然成立:

#include <stdio.h> 

struct { 
    unsigned m : 3; 
    unsigned n : 5; 
    unsigned o : 5; 
} b; 

int main(void) { 
    b.m = 1; 
    b.n = 1; 
    b.o = 1; 
    printf("%d\n",b); 
    return 0; 
} 

根據該假設的結構成員應該對齊這樣:

 
o o o o o n n n n n m m m 

並用二進制0000100001001在main分配給它們的值(即1,1和1)這將導致其在分解是265.

編譯和運行率:

$ gcc -Wall -o stprint stprint.c 
stprint.c: In function ‘main’: 
stprint.c:13:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct <anonymous>’ [-Wformat=] 
    printf("%d\n",b); 
    ^
$ ./stprint 
265 

即結果是(最有可能)驗證的假說。 希望我對這種行爲有所瞭解。


編輯/注:如果它不是來自上面的清晰,其他批評家指出,這種行爲依賴於實現,這意味着它是由編譯器來決定,如果這個「位聚合「發生與否,具體順序是什麼。人們還需要考慮底層平臺的字節順序(例如,參見here)。對於這篇文章,在Ubuntu系統中使用了gcc version 4.8.4

+0

是的,多個相鄰的位字段通常打包在一起(儘管這種行爲是實現定義的):如果它們是並且它們是從左到右或其他方式打包。資料來源:http://en.cppreference.com/w/cpp/language/bit_field – eckes

+0

@eckes是的,這是不言而喻的。這就是爲什麼我將此稱爲「計劃」和假設;這裏沒有什麼確定的。這篇文章的想法是在嘗試破譯一個奇怪的行爲時,爲思考位域智慧提供一個「kickstart」。在這種情況下,這是一個「降序」的順序;在其他人可能不會。感謝您的鏈接BTW。 – sokin

相關問題