16 Stimmen

Wie werden die Gewerkschaftsmitglieder gespeichert?

union test
{
 int i;
 char ch;
}t;
int main()
{
 t.ch=20;
}

Angenommen, sizeof(int)==2 und die für t zugewiesenen Speicheradressen seien 2000, 2001.
Wo ist dann 20, d.h. t.ch gespeichert - bei 2000 oder 2001 oder abhängig von der Endianness des Rechners?

21voto

Matteo Italia Punkte 119470

Der C99-Standard (§6.7.2.1.14) sagt:

Die Größe einer Gewerkschaft reicht aus, um die größten ihrer Mitglieder aufzunehmen. Der Wert von höchstens höchstens eines der Mitglieder kann jederzeit in einem Union-Objekt gespeichert werden. Ein Zeiger auf eine Union-Objekt, das entsprechend umgewandelt wurde, zeigt auf jedes seiner Mitglieder (oder wenn ein Mitglied ein bisschen- Feld ist, dann zu der Einheit, in der es sich befindet), und andersherum.

(Hervorhebung hinzugefügt)

Die fettgedruckte Aussage besagt, dass jedes Mitglied der Gewerkschaft die gleiche Adresse hat, also alle an der gleichen Adresse "anfangen". t als t.ch como t.i sollte unter der Adresse 2000 stehen, also t.ch überschneidet sich mit dem ersten Byte (in Adressreihenfolge) von t.i .

Was bedeutet das im Hinblick auf die Frage "Was bekomme ich, wenn ich versuche zu lesen? t.i nach der Einstellung t.c " hängt in der realen Welt von der Endianness der Plattform ab, und in der Tat ist der Versuch, ein Mitglied einer Union zu lesen, wenn man in eine andere geschrieben hat, ein unspezifiziertes Verhalten gemäß dem C-Standard (§6.2.6.1.6/7, wiedergegeben in §J.1.1).


Um die Endianness der Maschine besser zu verstehen (zumindest denke ich, dass es einfacher zu verstehen ist), ist es hilfreich, eine Vereinigung wie diese zu haben:

union
{
    int i;
    unsigned char ch[sizeof(i)];
} t;

bei

t.i=20;

und dann nachsehen, was in den beiden Zeichen bei t.ch . Wenn Sie auf einem Little-Endian-Rechner arbeiten, erhalten Sie t.ch[0]==20 y t.ch[1]==0 und das Gegenteil, wenn Sie auf einem Big-Endian-Rechner arbeiten (wenn sizeof(int)==2 ). Beachten Sie, dass dies, wie bereits gesagt, ein implementierungsspezifisches Detail ist, die Norm erwähnt nicht einmal die Endianness.

Um es noch deutlicher zu machen: Wenn Sie eine 2-Byte int var auf 20 gesetzt ist, erhält man auf einem Little-Endian-Rechner, wenn man den zugehörigen Speicher in Adressreihenfolge ausgibt, (in hexadezimaler Darstellung, Bytes durch Leerzeichen getrennt):

14 00

während Sie auf einem Big-Endian-Rechner Folgendes erhalten

00 14

Die Big-Endian-Darstellung sieht aus unserer Sicht "richtiger" aus, weil in der Little-Endian-Darstellung die Bytes, aus denen das Ganze besteht int werden in umgekehrter Reihenfolge gespeichert.


Außerdem sage ich, dass, wenn ich dies tue:

int a=20;
printf("%d",* (char*)&a);

Hängt die Ausgabe dann nicht von der Endian-Zugehörigkeit ab, d.h. ob 20 bei 2000 oder 2001 gespeichert wird?

Ja, hier schon, aber in Ihrer Frage geht es um etwas anderes; das sieht eher so aus meine Beispiel.

1voto

Jonathan Wood Punkte 61798

Test würde zwei Bytes benötigen und würde daher an der Adresse 2000, 2002 usw. zugewiesen werden. Und jeder Wert für jede Instanz der Vereinigung würde ab dieser Basisadresse gespeichert werden.

Jedes Mitglied der Vereinigung würde unter der gleichen Adresse für diese Instanz der Vereinigung gespeichert werden. Aus diesem Grund kann in einer Union nur ein Werttyp gleichzeitig gespeichert werden. Daher belegen Unions die für das größte Mitglied erforderliche Anzahl von Bytes.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X