2009-02-11 39 views
3

簡短版本是:如何學習C++字段的單個字段的大小(以位爲單位)?從C++ struct字段獲取單個字段的大小

爲了澄清,該領域的一個例子,我是說:

struct Test { 
    unsigned field1 : 4; // takes up 4 bits 
    unsigned field2 : 8; // 8 bits 
    unsigned field3 : 1; // 1 bit 
    unsigned field4 : 3; // 3 bits 
    unsigned field5 : 16; // 16 more to make it a 32 bit struct 

    int normal_member; // normal struct variable member, 4 bytes on my system 
}; 

Test t; 
t.field1 = 1; 
t.field2 = 5; 
// etc. 

爲了讓整個測試對象的大小很容易,我們只說

sizeof(Test); // returns 8, for 8 bytes total size 

我們可以得到一個正常的結構成員通過

sizeof(((Test*)0)->normal_member); // returns 4 (on my system) 

我想知道如何獲得單個字段的大小,說測試::字段4。以上正常結構成員的示例不起作用。有任何想法嗎?或者有人知道它無法工作的原因?我相當確信sizeof不會有幫助,因爲它只返回字節大小,但如果有人知道,否則我都是耳朵。

謝謝!

+0

我想你可能會被嘲笑,但我想證明是錯誤的。 – 2009-02-11 23:02:33

+0

我想借此機會繼續我對位域的討伐 - 只是不要使用它們: http://stackoverflow.com/questions/289900/why-this-unions-size-is-2-with- bitfields/290855#290855 – 2009-02-11 23:34:52

回答

10

您可以在運行時,FWIW,例如計算大小:

//instantiate 
Test t; 
//fill all bits in the field 
t.field1 = ~0; 
//extract to unsigned integer 
unsigned int i = t.field1; 
... TODO use contents of i to calculate the bit-width of the field ... 
+0

這樣做沒什麼意義,爲什麼不只是使用已經提到的其他編譯時間建議? – 2009-02-11 23:42:34

1

這是不可能的

答評論: 因爲類型僅僅是一個整數,沒有「位」類型。位字段分配語法僅用於執行讀取和寫入的按位代碼。

+0

你有一些文件指向我嗎?或者至少你的推理?我只是好奇而已。 – 2009-02-11 23:08:30

1

我認爲你不能這樣做。如果你真的需要的尺寸,我建議你使用一個#define(或者更好的是,如果可能的話const變量 - 我不知道這是合法的),像這樣:

#define TEST_FIELD1_SIZE 4 
struct Test { 
    unsigned field1 : TEST_FIELD1_SIZE; 
    ... 
} 
+0

const是合法的,只要它是一個整數類型(畢竟不能保留一半)。這是我能夠做得最好的。謝謝。 – 2009-02-11 23:12:11

5

你可以不拿sizeof一個位域並獲得位數。

你最好的選擇是使用#define S或enum S:

struct Test { 
    enum Sizes { 
     sizeof_field1 = 4, 
     sizeof_field2 = 8, 
     sizeof_field3 = 1, 
     sizeof_field4 = 3, 
     sizeof_field5 = 16, 
    }; 

    unsigned field1 : sizeof_field1; // takes up 4 bits 
    unsigned field2 : sizeof_field2; // 8 bits 
    unsigned field3 : sizeof_field3; // 1 bit 
    unsigned field4 : sizeof_field4; // 3 bits 
    unsigned field5 : sizeof_field5; // 16 more to make it a 32 bit struct 

    int normal_member; // normal struct variable member, 4 bytes on my system 
}; 

printf("%d\n", Test::sizeof_field1); // prints 4 

出於一致性的緣故,我相信你可以移動normal_member到頂部,並添加使用sizeof(normal_member)Sizes的條目。不過,這與你的數據順序混亂。

2

使用ChrisW's idea(好的,順便說一句),你可以創建一個幫助宏:

#define SIZEOF_BITFIELD(class,member,out) { \ 
    class tmp_;        \ 
    tmp_.member = ~0;      \ 
    unsigned int tmp2_ = tmp_.member;  \ 
    ++tmp2_;        \ 
    out = log2(tmp2_);      \ 
} 

unsigned int log2(unsigned int x) { 
    // Overflow occured. 
    if(!x) { 
     return sizeof(unsigned int) * CHAR_BIT; 
    } 

    // Some bit twiddling... Exploiting the fact that floats use base 2 and store the exponent. Assumes 32-bit IEEE. 
    float f = (float)x; 
    return (*(unsigned int *)&f >> 23) - 0x7f; 
} 

用法:

size_t size; 
SIZEOF_BITFIELD(Test, field1, size); // Class of the field, field itself, output variable. 

printf("%d\n", size); // Prints 4. 

我使用模板功能的嘗試都失敗了。我不是模板方面的專家,但是,它可能可能仍然可能有一個乾淨的方法(例如sizeof_bitfield(Test::field1))。