Welches Ende eines Bitfeldes ist das höchstwertige Bit?

Lesezeit: 2 Minuten

Benutzeravatar von Jim Fell
Jim fiel

Ich schreibe eine C++-Anwendung für Windows XP/Vista/7 mit Visual Studio 2008. Einige meiner Strukturen verwenden ein Bitfeld, wie im Beispiel gezeigt.

typedef struct myStruct_tag
{
    BYTE myVar1;
    WORD myVar2;
    WORD myVar3;
    union
    {
        struct
        {
            BYTE           :1;
            BYTE field1    :1;
            BYTE field2    :1;
            BYTE reserved  :5;
        } myBitField;
        BYTE myVar4;
    };
    BYTE myVar5;
    BYTE myVar6;
} myStruct_t;

Welches Ende des Feldes ist das höchstwertige Bit?

  • Hinweis: Laut Standard ist das MSB nicht definiert. Auf Ihrer spezifischen Plattform vermute ich das reserved enthält das MSB, aber ich bin nicht sicher.

    – Billy ONeal

    28. Dezember 2010 um 16:24 Uhr

  • @ Billy: Das sieht für mich nach einer Antwort aus.

    – Ben Voigt

    28. Dezember 2010 um 16:26 Uhr

  • Äh … Das ist eine ziemlich seltsame Frage. Sie haben nur 3 Bitfelder in Ihrer Deklaration. 2 davon sind 1-Bit-Bitfelder, dh es gibt keine Frage, “welches Ende” bei ihnen gibt, da dort nur 1 Bit vorhanden ist. Das einzige Multi-Bit-Bit-Feld namens reserved, was darauf hindeutet, dass es überhaupt nicht verwendet wird. Das einzige Bitfeld, auf das Sie sich beziehen können, ist also im Grunde genommen reserved. Fragst du nach reserved speziell? Wenn nicht, präzisieren Sie Ihre Frage.

    – AnT steht zu Russland

    28. Dezember 2010 um 16:26 Uhr

  • @Ben: Wenn ich positiv wäre, welche Variable das MSB bekommen würde, wäre es eine Antwort gewesen, aber ich bin nicht sicher …

    – Billy ONeal

    28. Dezember 2010 um 16:27 Uhr

  • Dies ist wichtig, da die Struktur verwendet wird, um ein Paket für die serielle Kommunikation zu definieren. Die Bitfelder müssen auf beiden Seiten des Systems ausgerichtet werden, wobei ich leider nur über eine Seite die Kontrolle habe.

    – Jim fiel

    28. Dezember 2010 um 16:30 Uhr

C99-Standard 6.7.2.1/10 (Hervorhebung von mir):

Eine Implementierung kann jede adressierbare Speichereinheit zuweisen, die groß genug ist, um ein Bitfeld zu halten. Wenn genügend Platz verbleibt, soll ein Bitfeld, das in einer Struktur unmittelbar auf ein anderes Bitfeld folgt, in benachbarte Bits derselben Einheit gepackt werden. Wenn nicht genügend Platz verbleibt, ist es implementierungsdefiniert, ob ein Bitfeld, das nicht passt, in die nächste Einheit eingefügt wird oder benachbarte Einheiten überlappt. Die Reihenfolge der Zuweisung von Bitfeldern innerhalb einer Einheit (von hoher Ordnung zu niedriger Ordnung oder von niedriger Ordnung zu hoher Ordnung) ist implementierungsdefiniert. Die Ausrichtung der adressierbaren Speichereinheit ist nicht spezifiziert.

Die Reihenfolge muss also von Ihrer Compiler-Implementierung dokumentiert werden.

Allerdings ist so viel über die Implementierung von Bitfeldern implementierungsdefiniert oder unspezifiziert, dass ihre Verwendung zum Modellieren von Hardware-, Drahtprotokoll- oder Dateiformat-Bitfeldern auf tragbare Weise den Versuch nicht wert ist.

Wenn Sie möchten, dass Ihre “Bitfelder” etwas außerhalb Ihres Programms modellieren (wie die obigen Dinge), verwenden Sie explizite Masken, setzen und löschen Sie die Bits mit den standardmäßigen bitweisen Operatoren (|‘&,~,<<` usw.). Verwenden Sie Inline-Hilfsfunktionen (oder sogar Makros, wenn Sie müssen), um dies in Ihrem Code einfacher/klarer zu machen.

  • +10, wenn ich könnte. Ihre Antwort auf diese Frage ist der beste Grund, Bitfields nicht für die Hauptsache zu verwenden, für die die Leute sie für nützlich halten.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    28. Dezember 2010 um 19:44 Uhr

  • Ich wusste nicht, dass Leute versuchen, sie portabel zu verwenden, die einzige Verwendung, die ich gesehen habe, ist “mit Hardware von meinem Programm sprechen, das Compiler X verwendet”. Und schauen Sie sich all die Millionen von “Ich mache das in Compiler X, wie mache ich das in Compiler Y”-Fragen an.

    – Code-Abominator

    14. April 2015 um 0:13 Uhr

  • @CodeAbominator: Als Beispiel habe ich Bitfelder gesehen, die zum Knacken von Netzwerkprotokollnachrichten oder binären Dateiformaten verwendet werden. Ich habe auch gesehen, dass ein Teil dieses Codes nicht funktioniert, wenn er für eine andere Plattform kompiliert wurde.

    – Michael Burr

    15. April 2015 um 7:14 Uhr

  • Genau dafür werden Bitfelder verwendet. Es wäre nützlich, wenn ein zukünftiger C-Standard dieses Verhalten definieren würde, aber in der Embedded-Welt sind Bitfelder und Vereinigungen notwendig und werden von Programmierern und Geräteherstellern in ihren Header-Dateien verwendet. Seien Sie vorsichtig, lesen Sie die Compiler-Dokumentation und erwarten Sie nicht, dass sie portierbar ist. Verwendung in hardwareabhängigem Low-Level-Code, wo es notwendig ist, bestimmte Bits zu spezifizieren und wo die Verwendung von Masken die Codegröße erhöhen, die Leistung verringern und keinen Nutzen bringen würde (da diese Art von Code per Definition nicht portierbar ist).

    – Benutzer1582568

    8. November 2020 um 18:51 Uhr

Die Visual Studio 2008-Compilerdokumentation gibt Folgendes an:

Die Reihenfolge der als Bitfelder deklarierten Daten ist von niedrigem zu hohem Bit

Aus „C++-Bitfelder“, MSDN C++-Sprachreferenz, Visual Studio 2008-Version

  • Wie andere angemerkt haben, geben die einschlägigen Standards dies nicht an, und es ist schön, standardkonformen Code zu schreiben, aber dies ist die Antwort auf die gestellte Frage, und der Leser kann entscheiden, ob er seine Befugnisse für immer nutzen möchte oder für toll. ;P

    – rakslice

    23. Februar 2017 um 8:08 Uhr


Wenn Sie fragen, welche Bits in myBitField in welchen Bits des Bytes im Speicher gespeichert werden, ist dies durch die C-Standards ausdrücklich nicht definiert. Sie müssen durch Experimentieren lernen. Es lohnt sich wahrscheinlich, wenn Sie etwas tun, bei dem dies tatsächlich wichtig ist, stattdessen einen Ansatz zu verwenden, bei dem Sie #definieren field1 als Hex-Wert (z. B. 0x40 oder 0x02) und platzieren Sie es an der gewünschten Stelle.

  • Leider ist das funktionale Testen dieses Teils des Codes noch mindestens Wochen, wenn nicht Monate entfernt. (Es gibt eine Menge, die geschrieben werden muss, um wirklich etwas davon zu testen, weil ich jetzt an einem Punkt angelangt bin, an dem alles, was noch zu schreiben ist, mehr oder weniger von allem anderen abhängt.) Definierte Konstanten sind eine Option, aber ich würde es vorziehen Bitfelder zu verwenden, da ersteres a erfordern würde viel mehr Logik in meinem Code.

    – Jim fiel

    28. Dezember 2010 um 16:36 Uhr

  • Nun, ein kurzes Experiment sollte Ihnen zeigen, was der Compiler jetzt macht … definieren Sie einfach die Union wie oben, weisen Sie 0 zu myVar4dann 1 zuweisen field1 und drucken Sie den resultierenden Wert aus myVar4. Ich würde einen Namen an das unbenutzte Bit hängen, das Sie zuvor definiert haben field1damit der Compiler es nicht wegoptimiert.

    – Jay Maynard K5ZC

    28. Dezember 2010 um 16:58 Uhr

1432770cookie-checkWelches Ende eines Bitfeldes ist das höchstwertige Bit?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy