2013-07-20 40 views
3

假設我的項目包括從包含該第三方庫頭:如何計算有符號位域的最大支持值?

struct foo { 
    signed int x:4; 
}; 

沒有假設位字段總會有寬4,並且不依賴於實現定義的行爲,我怎麼能確定可存儲在會員x中的最大值?

+0

可靠地,您只能存儲'1111'。 –

+1

@GrijeshChauhan:「沒有假設位域將始終具有寬度4」。第三方開發者可能會在下一個版本中將寬度更改爲5。或者13.或者其他的東西。當位域的寬度發生變化時,我不希望我的代碼中斷。 –

+0

我沒有得到:(,*'不假設位字段將始終具有寬度4 * *它將始終有4 - 與任何編譯器...我錯過了什麼嗎? –

回答

1

基本上你不能。問題與確定INT_MAXINT_MIN相同:因爲你自己無法確定這些,所以編譯器實現必須爲提供這些值。 (你所能做的只是確定符號位的位置是否定義了實現(甚至是未定義的)行爲:溢出,移位運算符)

對於位域,實現不能提供這些值,所以你被卡住了。

這是bitfields真的不應該是signed的原因之一。位字段用於位操作,沒有別的,符號位則被浪費了。

如果你的領域是unsigned事情會很容易。你只需要在其中存儲-1,你會得到所有的值,即「類型」的最大值。

5

,因爲它不能與sizeof計算位字段的大小,這可以幫助:

#include <stdio.h> 

struct foo { 
    signed int x: 4; 
}; 

#define BIT(n) (1l << (n)) 
#define BIT_MASK(len) (BIT(len) - 1) 

int main(void) 
{ 
    struct foo f = {0}; 
    long i = 0; 

    while (f.x >= 0) { 
     f.x = BIT_MASK(++i); 
    } 
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i)); 
    return 0; 
} 

左移,直到f.x爲負。

編輯:

上面的代碼是實現定義的,檢查這一項,我認爲這會工作(但你必須處理大端):

#include <stdio.h> 
#include <string.h> 

struct foo { 
    signed int x: 4; 
}; 

#define BIT(n) (1l << (n)) 
#define BIT_MASK(len) (BIT(len) - 1) 

int main(void) 
{ 
    long x, i = 0; 
    struct foo f; 

    f.x = -1; 
    memcpy(&x, &f, sizeof(f)); 
    while (1) { 
     if (!(x & BIT(++i))) break; 
    } 
    printf("bits=%ld max=%ld\n", i, BIT_MASK(i)); 
    return 0; 
} 

,你可以現在看它不超過2 ^(n-1)-1(作品在long

+2

這是非常好的答案! David RF你應該添加一些評論和解釋。 –

+1

OP(@Richard漢森):選中此代碼工作@ [鍵盤](http://codepad.org/aWKoshW3) –

+1

謝謝Grijesh;) –

0

如果我這樣做,我會嘗試加載一個-1,如果它是2的補碼錶示,那麼它將是可以存儲的最大正值。 以上案例

foo.x = -1; unsigned int max_size =(unsigned int)(foo.x);

其中一半將是無符號最大值,一半+ 1將是最大符號值