Komme på størrelse med en indiviual felt fra en c ++ struct felt

stemmer
3

Kortversjonen er: Hvordan kan jeg lære størrelsen (i biter) av en enkelt felt av en C ++ feltet?

For å klargjøre, et eksempel på det feltet jeg snakker om:

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.

For å få størrelsen på hele testobjekt er enkelt, vi bare si

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

Vi kan få en normal struct medlem gjennom

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

Jeg vil gjerne vite hvordan du får på størrelse med et enkelt felt, sier Test :: field4. Eksempelet ovenfor for en normal struct medlem virker ikke. Noen ideer? Eller vet noen en grunn til at det ikke kan fungere? Jeg er ganske overbevist om at sizeof ikke vil være til hjelp, siden det bare returnerer størrelse i byte, men hvis noen vet ellers er jeg lutter øre.

Takk!

Publisert på 11/02/2009 klokken 22:57
kilden bruker
På andre språk...                            


6 svar

stemmer
10

Du kan beregne størrelsen under kjøring, FWIW, for eksempel:

//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 ...
Svarte 11/02/2009 kl. 23:16
kilden bruker

stemmer
5

Du kan ikke ta sizeofen bitfield og få antall bits.

Det beste alternativet ville være bruk #defines eller enums:

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

For å få til konsistensen, tror jeg du kan flytte normal_memberopp til toppen, og legge til en oppføring i Sizeshjelp sizeof(normal_member). Dette roter med rekkefølgen på dataene, skjønt.

Svarte 11/02/2009 kl. 23:08
kilden bruker

stemmer
3

Virker usannsynlig, siden sizeof () er i byte, og du vil ha biter.

http://en.wikipedia.org/wiki/Sizeof

bygge på litt telling svar, kan du bruke.

http://www-graphics.stanford.edu/~seander/bithacks.html

Svarte 11/02/2009 kl. 23:10
kilden bruker

stemmer
2

Ved hjelp av ChrisW idé (fint, forresten), kan du lage en hjelper makro:

#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;
}

bruk:

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

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

Mine forsøk på å bruke malbasert funksjoner har mislyktes. Jeg er ikke ekspert på maler, men slik at det kan fortsatt være mulig å ha en ren metode (f.eks sizeof_bitfield(Test::field1)).

Svarte 12/02/2009 kl. 00:54
kilden bruker

stemmer
1

Jeg tror ikke du kan gjøre det. Hvis du virkelig trenger størrelse, foreslår jeg at du bruker en #define(eller enda bedre, hvis mulig en constvariabel - Jeg er ikke sikker på om det er lovlig) som så:

#define TEST_FIELD1_SIZE 4
struct Test {
    unsigned field1 : TEST_FIELD1_SIZE;
    ...
}
Svarte 11/02/2009 kl. 23:07
kilden bruker

stemmer
1

Dette er ikke mulig

Svar å kommentere: Fordi typen er bare en int, er det ingen 'bit' type. Bit feltet oppdraget syntaks er bare kort hånd for å utføre bitvis koden for leser og skriver.

Svarte 11/02/2009 kl. 23:06
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more