2013-11-25 10 views
13

Würde jemand wissen, wie man die Größe eines Bit-Feld Mitglied zu extrahieren. Der folgende Code gibt mir natürlich die Größe einer Ganzzahl, aber wie finde ich heraus, wie viele Bits oder Bytes in mybits.one sind? Ich habe versucht sizeof(test.one), aber was eindeutig nicht funktioniert. Ich weiß, das ein Maß für Bits:Größe eines Bitfeld-Mitglieds?

#include <iostream> 

using namespace std; 

int main() 
{ 
    struct mybits { 
     unsigned int one:15; 
    }; 

    mybits test; 
    test.one = 455; 
    cout << test.one << endl; 
    cout << "The size of test.one is: " << sizeof(test) << endl; 
} 
+1

Runtime-Lösung: Setzen Sie den Wert der gesamten Struktur auf Null, dann invertieren Sie das Feld mit "~" und zählen Sie dann die Anzahl der Bits auf "1". http://social.msdn.microsoft.com/Forums/en-US/7e4f01b6-2e93-4acc-ac6a-b994702e7b66/finding-size-of-bitfield –

Antwort

5

Runtime-Lösung, die Idee aus dieser Diskussion: http://social.msdn.microsoft.com/Forums/en-US/7e4f01b6-2e93-4acc-ac6a-b994702e7b66/finding-size-of-bitfield

#include <iostream> 
using namespace std; 

int BitCount(unsigned int value) 
{ 
    int result = 0; 

    while(value) 
    { 
     value &= (value - 1); 
     ++result; 
    } 

    return result; 
} 

int main() 
{ 
    struct mybits { 
     unsigned int one:15; 
    }; 

    mybits test; 
    test.one = ~0; 

    cout << BitCount(test.one) << endl; 

    return 0; 
} 

Drucke 15.

+0

Danke dafür .. Das ist gut. – domonica

+1

nicht sicher, aber dies kann vom Compiler abhängen, da es nicht definiert ist, wie die aufgefüllten Bits gesetzt sind. Sie können Müll enthalten. Also, pass auf, wie du das verwendest. Außerdem ist es zur Laufzeit fertig. –

+0

@ BЈOVћћ: Nur 'test.one' wird an' BitCount' übergeben, es sollte keine aufgefüllten Bits enthalten. Es ist möglich, zuerst die gesamte Struktur auf Null zu setzen, aber ich glaube nicht, dass es notwendig ist. –

1

Wegen padding es nicht möglich ist die Anzahl der Bits in einem Bit-Feld, um zu sehen mit sizeof-Operator.

Die einzige Möglichkeit besteht darin, den Header zu öffnen, in dem die Struktur definiert ist, und nachzuschlagen.

+0

Ok, danke. Aber wenn ich den Typ in char ändere und 8 Bits in der Größe des Bitfeldelements überschreite, kann ich die Funktion sizeof verwenden, um die aufgerundete Anzahl von Bytes zu bestimmen. Der Compiler warnt mich davor, die Größe von char 8 Bits in einem Bitfeld zu überschreiten. Ist es noch ok, es zu tun? Wird es später Probleme verursachen? – domonica

+0

@domonica Zuallererst hoffe ich wirklich, dass Sie Compilerwarnungen nicht ignorieren, da es die Sache ist, die schlampige Leute tun. Nicht sicher, was passieren wird. Es kann ein undefiniertes oder implementierungsdefiniertes Verhalten sein.In jedem Fall würde ich es nicht tun –

+0

Danke an alle, ein paar wirklich nützliche Punkte hier. Und, ich verspreche, ich werde Compiler-Warnungen nicht ignorieren. – domonica

1

Es gibt keine Möglichkeit, diese Informationen zu erhalten (abgesehen davon, dass Sie die Erklärung selbst gelesen haben). Gemäß dem Standard, [C++11]expr.sizeof§1, ist es illegal sizeof auf einem Bit-Feld zu nennen:

Der Operator sizeof gilt nicht für ... Lvalue angewandt werden, die ein Bitfeld bezeichnet.

1

Die draft C++ standard sagt sizeof ist nicht auf ein Bit-Feld in Abschnitt 5.3.3Sizeof angewendet werden Absatz . Wenn Sie die Kontrolle über die Quelle haben dann eine Enum mit klingt viel einfacher und übersichtlicher:

struct mybits 
{ 
    enum bitFieldSizes 
    { 
     field1 = 15, 
     field2 = 2, 
     field3 = 4, 
     field4 = 8, 
     field5 = 31 
    }; 

    unsigned int one : field1 ; 
    unsigned int two : field2 ; 
    unsigned int three : field3 ; 
    unsigned int four : field4 ; 
    unsigned int five : field5 ; 
}; 

Wenn Sie noch nicht die Kontrolle über die Quelle es möglich ist, etwas zu verwenden, hackt die Größe des Bit zu erhalten -field und std::bitset erleichtert:

#include <iostream> 
#include <bitset> 

struct mybits 
{ 
    unsigned int one : 15 ; 
    unsigned int two : 2 ; 
    unsigned int three : 4 ; 
    unsigned int four : 8 ; 
    unsigned int five : 31 ; 
}; 

int main() 
{ 
    mybits mb1 ; 

    mb1.one = ~0 ; 
    mb1.two = ~0 ; 
    mb1.three = ~0 ; 
    mb1.four = ~0 ; 
    mb1.five = ~0 ; 

    std::bitset<sizeof(unsigned int)*8> b1(mb1.one); 
    std::bitset<sizeof(unsigned int)*8> b2(mb1.two); 
    std::bitset<sizeof(unsigned int)*8> b3(mb1.three); 
    std::bitset<sizeof(unsigned int)*8> b4(mb1.four); 
    std::bitset<sizeof(unsigned int)*8> b5(mb1.five); 

    std::cout << b1 << ":" << b1.count() << std::endl ; 
    std::cout << b2 << ":" << b2.count() << std::endl ; 
    std::cout << b3 << ":" << b3.count() << std::endl ; 
    std::cout << b4 << ":" << b4.count() << std::endl ; 
    std::cout << b5 << ":" << b5.count() << std::endl ; 
} 

, die die folgende Ausgabe erzeugt:

00000000000000000111111111111111:15 
00000000000000000000000000000011:2 
00000000000000000000000000001111:4 
00000000000000000000000011111111:8 
01111111111111111111111111111111:31 
0

hier ein littl ist e bisschen schwierig generali Version:

#include <iostream> 
#include <limits> 
#include <bitset> 
#include <cstring> 
using namespace std; 

template <class T> 
T umaxof() 
{ 
     T t; 
     memset(&t, 0xFF, sizeof(T)); 
     return t; 
} 

template <class T> 
size_t bitsof(const T& umax) 
{ 
    return bitset<sizeof(T)*8>(umax).count(); 
} 

int main() 
{ 
    struct A 
    { 
     uint32_t bf1:19; 
     uint32_t bf2:1; 
    }; 

    cout << bitsof(umaxof<A>().bf1) << "\n"; 
    cout << bitsof(umaxof<A>().bf2) << "\n"; 

    return 0; 
} 

Es befindet sich auf https://ideone.com/v4BiBH

Hinweis ausprobiert werden kann: Arbeitet mit nur unsignierten Bit-Feldern.