Getting the size of a single field from a struct C ++ field

Short version: How to find out the size (in bits) of an individual field in a C ++ field?

To clarify, an example of the field I'm talking about:

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.

To get the size of the entire test object easily, just say

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

We can get the normal member of the structure through

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

I would like to know how to get the size of an individual field, for example Test :: field4. The above example for a regular structure element does not work. Any ideas? Or does someone know the reason why he cannot work? I'm pretty sure sizeof won't help, since it only returns size in bytes, but if someone knows otherwise, I'm all ears.

Thank!

+3
source share
6 answers

, 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 ...
+10

sizeof .

#define 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 Sizes sizeof(normal_member). .

+5

ChrisW 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)).

+2

: int, "". - .

+1

I do not think you can do this. If you really need size, I suggest you use #define(or, even better, if possible, a variable const- I'm not sure if this is legal):

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

All Articles