Wie wird die Größe einer Struktur mit Bitfeldern bestimmt/gemessen?

Lesezeit: 5 Minuten

Jagans Benutzeravatar
Jagan

#include <stdio.h>

typedef struct size
{
        unsigned int a:1;
        unsigned int b:31;
        unsigned int c:1;
} mystruct;

int main()
{
        mystruct a;
        printf("%d", sizeof(a));
        return 0;
}
  • Mit int b:31die Ausgabe ist 8.
  • Mit int b:1die Ausgabe ist 4.
  • Mit int b:32die Ausgabe ist 12.

Kann jemand den Grund dafür erklären?

  • Wenn Sie schon immer wissen wollten, wann ein 64-Bit-Computer weniger Speicherplatz benötigt als ein 32-Bit-Computer (oder zumindest nicht mehr Speicherplatz als ein 32-Bit-Computer), dann ist dies ein Beispiel.

    – Jonathan Leffler

    9. November 2010 um 2:37 Uhr

  • @JonathanLeffler: Bist du sicher? GCC auf x64 Linux/ELF sagt, dass die Größe 12 für den Fall (1,32,1) ist. Ich glaube, das Einzige, was die Größe solcher Strukturen beeinflusst, ist die Größe des zugrunde liegenden Typs, was in diesem Fall der Fall ist unsigned int.

    – Dietrich Ep

    23. Dezember 2012 um 4:12 Uhr

  • @DietrichEpp: ISO/IEC 9899:2011 §6.7.2.1 Struktur- und Vereinigungsspezifizierer: Der Ausdruck, der die Breite eines Bitfelds angibt, muss ein ganzzahliger konstanter Ausdruck mit einem nicht negativen Wert sein, der die Breite eines Objekts des Typs nicht überschreitet, der angegeben würde, wenn der Doppelpunkt und der Ausdruck weggelassen würden. Ich denke, das stützt Ihre Behauptung … aber wenn wir eine ILP64-Maschine finden würden (anstelle der üblichen LP64-Maschinen), würde ich mich darum winden.

    – Jonathan Leffler

    23. Dezember 2012 um 6:14 Uhr

Auf die Reihenfolge kommt es an. Der folgende Code gibt Ausgabe: 8

#include<stdio.h>

typedef struct size
{
        unsigned int b:32;
        unsigned int a:1;
        unsigned int c:1;
}mystruct;

int main(int argc, char const *argv[])
{
        mystruct a;
        printf("\n %lu \n",sizeof(a));
        return 0;
}

Unsigned int ist eine 32-Bit-Ganzzahl, die 4 Bytes belegt. Speicher wird zusammenhängend im Speicher zugewiesen.


Option 1:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:31;      // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Second 4 bytes are allocated

Ausgabe: 8


Option 2:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:32;      // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated
unsigned int c:1;       // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated

Ausgabe: 12


Möglichkeit 3:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:1;       // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Will get accomodated in the First 4 bytes

Ausgabe: 4


Möglichkeit 4:

unsigned int b:32;      // First 4 bytes are allocated
unsigned int a:1;       // Second 4 bytes are allocated
unsigned int c:1;       // Will get accomodated in the Second 4 bytes

Ausgabe: 8

  • Dies sollte meiner Meinung nach die akzeptierte Antwort sein.

    – Zephyr

    21. Juli 2017 um 14:13 Uhr

  • Die Position des Bitfelds bestimmt die Größe, da es das Auffüllen bewirkt. Wie es für die Struktur empfohlen wird, das höchste. größte Element oben zu haben, um die beste / minimale Polsterung zu haben

    – asch

    4. Juni 2020 um 5:31 Uhr

  • Richtig, diese Antwort sollte akzeptiert werden. Obwohl MdT es 3 Jahre später veröffentlicht hat. Wie auch immer – viel aus diesem Kommentar gelernt. Viele Dinge, die ich aus diesem Beitrag gelernt habe, wusste ich nicht.

    – todovvox

    21. November 2021 um 11:48 Uhr

  • @Zephyr Dies sollte meiner Meinung nach die akzeptierte Antwort sein. Nein. Diese Antwort ist falsch. Der Kommentar Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated ist NICHT WAHR. Gemäß dem C-Standard: “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.”

    – Andreas Henle

    15. Dezember 2021 um 15:16 Uhr


Sie sagen nicht, ob Sie wissen, was Bitfelder sind, aber ich gehe davon aus, dass Sie es wissen.

An deiner Implementierung offensichtlich unsigned int ist eine 32-Bit-Ganzzahl, die 4 Bytes belegt. Dies erklärt das erste und zweite Beispiel. Offensichtlich passen 3 Bitfelder mit insgesamt 33 Bits nicht in ein einziges unsigned int, daher die Notwendigkeit von 8 Bytes im ersten Beispiel. 3 Bitfelder mit insgesamt 3 Bit passen sicherlich in eine unsigned intalso nur 4 Bytes im zweiten Beispiel.

Außerdem kann ein Bitfeld nicht mehrere ganze Zahlen umfassen. Dies erklärt das dritte Beispiel. Ich kann mich nicht erinnern, ob dies eine Anforderung des Standards oder nur ein Detail Ihrer Implementierung ist. So oder so, seitdem b ist 32 Bit, es füllt ein Ganzes unsigned int allein, zwingt beide a und c ihre eigenen zu besetzen unsigned int, vor und nach dem mittleren. Also 12 Byte.

Benutzeravatar von Yuan
Yuan

Laut Steve Jessops Antwort, nur um seine Antwort zu erfüllen, indem einige Dokumente hinzugefügt werden, die hilfreich sein können.

Ein Mitglied einer Struktur oder Union kann jeden vollständigen Objekttyp außer einem variabel modifizierten Typ haben. Außerdem kann ein Mitglied so deklariert werden, dass es aus einer bestimmten Anzahl von Bits besteht (einschließlich eines Vorzeichenbits, falls vorhanden). Ein solches Mitglied wird a genannt Bitfeld seiner Breite ist ein Doppelpunkt vorangestellt

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.

Innerhalb eines Strukturobjekts haben die Mitglieder, die keine Bitfelder sind, und die Einheiten, in denen sich Bitfelder befinden, Adressen, die in der Reihenfolge ansteigen, in der sie deklariert werden. Ein geeignet umgewandelter Zeiger auf ein Strukturobjekt zeigt auf sein Anfangselement (oder, wenn dieses Element ein Bitfeld ist, dann auf die Einheit, in der es sich befindet) und umgekehrt. Innerhalb eines Strukturobjekts kann es unbenannte Auffüllungen geben, jedoch nicht an seinem Anfang.

——ISO/IEC 9899:201x 6.7.2.1

  • Und man sollte insbesondere beachten, dass der deklarierte Typ eines Bitfelds nicht die Größe der adressierbaren Speichereinheit bestimmt, in der sein Wert gespeichert wird. Der deklarierte Typ begrenzt die zulässige Bitfeldbreite, und Bitfeldbreiten interagieren mit ASU-Größen, aber es gibt einen großen Spielraum für Variationen im Layout.

    – Johannes Bollinger

    15. Dezember 2021 um 15:38 Uhr


Ausrichtung

Der Compiler rundet die Größe der Struktur auf 32 Bit, die Größe jedes Objekts, auf das er möglicherweise verweist, auf 32 Bit und behält gleichzeitig die Reihenfolge Ihrer Bitfelder bei.

Wenn Sie also ein 32-Bit-Element in der Mitte und 1-Bit-Elemente auf jeder Seite haben, müssen 3 32-Bit-Wörter zugewiesen werden, also 12 Bytes.

In den anderen beiden Fällen geht es nur darum, in wie wenige 32-Bit-Objekte Ihre Bitfeldsequenz gepackt werden kann, während die Feldreihenfolge erhalten bleibt.

1399810cookie-checkWie wird die Größe einer Struktur mit Bitfeldern bestimmt/gemessen?

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

Privacy policy