union test
{
int i;
char ch;
}t;
int main()
{
t.ch=20;
}
Vermuten sizeof(int)==2
und die für t zugewiesenen Speicheradressen seien 2000, 2001.
Wo ist dann 20, dh t.ch
gespeichert – bei 2000 oder 2001 oder hängt von der Endianness der Maschine ab?
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 einem der Mitglieder kann jederzeit in einem Union-Objekt gespeichert werden. Ein Zeiger auf ein Vereinigungsobjekt, geeignet konvertiert, zeigt auf jedes seiner Mitglieder (oder wenn ein Mitglied ein Bitfeld ist, dann an die Einheit, in der es sich befindet) und umgekehrt.
(Betonung hinzugefügt)
Die fette Aussage besagt eigentlich, dass jedes Mitglied der Gewerkschaft die gleiche Adresse hat, also „beginnen“ sie alle an der gleichen Adresse. t
wie t.ch
wie t.i
sollte also an der Adresse 2000 liegen t.ch
überschneidet sich mit dem ersten Byte (in Adressreihenfolge) von t.i
.
Was das in Bezug auf „was bekomme ich, wenn ich versuche zu lesen t.i
nach Einstellung t.c
” hängt in der realen Welt von der Plattformendianität ab, und tatsächlich ist der Versuch, ein Mitglied einer Gewerkschaft zu lesen, wenn Sie in einer anderen geschrieben haben, gemäß dem C-Standard ein nicht spezifiziertes Verhalten (§6.2.6.1.6/7, neu formuliert in §J. 1.1).
Was mehr hilft, die Endianness der Maschine zu verstehen (zumindest denke ich, dass es einfacher zu verstehen ist), ist eine Union wie diese:
union
{
int i;
unsigned char ch[sizeof(i)];
} t;
tun
t.i=20;
und dann schauen, was in den beiden Zeichen ist t.ch
. Wenn Sie sich auf einer Little-Endian-Maschine befinden, erhalten Sie t.ch[0]==20
und t.ch[1]==0
und das Gegenteil, wenn Sie sich auf einer Big-Endian-Maschine befinden (if sizeof(int)==2
). Beachten Sie, dass dies, wie bereits gesagt, ein implementierungsspezifisches Detail ist, der Standard erwähnt nicht einmal Endianness.
Um es noch deutlicher zu machen: Wenn Sie ein 2-Byte haben int
var auf 20 gesetzt, auf einer Little-Endian-Maschine den zugehörigen Speicher in Adressreihenfolge ausgeben, erhalten Sie (in hexadezimaler Darstellung, Bytes durch Leerzeichen geteilt):
14 00
während auf einer Big-Endian-Maschine erhalten Sie
00 14
Die Big-Endian-Darstellung sieht aus unserer Sicht “richtiger” aus, denn in der Little-Endian-Darstellung machen die Bytes das Ganze aus 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 Endianität ab, dh ob 20 bei 2000 oder 2001 gespeichert wird?
Ja, hier tut es das, aber in Ihrer Frage fragen Sie etwas anderes; das sieht eher aus mein Beispiel.
test würde zwei Bytes benötigen und würde daher an Adresse 2000, 2002 usw. zugewiesen werden. Und jeder Wert für jede Instanz der Vereinigung würde beginnend an dieser Basisadresse gespeichert werden.
Jedes Mitglied der Vereinigung würde für diese Instanz der Vereinigung an der gleichen Adresse gespeichert werden. Aus diesem Grund können Sie nur einen Werttyp gleichzeitig in einer Union speichern. Daher belegen Vereinigungen die Anzahl von Bytes, die für das größte Element erforderlich sind.
Ich bin mir nicht sicher, ob die Endianität etwas damit zu tun hat, wo eine Union gespeichert wird … speichern nicht alle Union-Typen am selben Ort (dh am Nullpunkt)? (Trotzdem gute Frage!)
– Platin Azur
27. Dezember 2010 um 17:54 Uhr
2001 ist unwahrscheinlich, da nicht ausgerichteter Speicherzugriff je nach Architektur entweder langsam oder verboten ist.
– Alexander C.
27. Dezember 2010 um 17:56 Uhr
@Platinum Azure: Wenn wir einfach int a=20 definieren; hängt es dann nicht von endianness ab, wo 20 gespeichert ist?
– Glücklicher Mittal
27. Dezember 2010 um 18:01 Uhr
@Happy Mittal: Nein, weil Sie nur sagen, dass es unabhängig davon zwei Bytes (sowohl 2000 als auch 2001 in Ihrem Beispiel) verwendet. Nun, ob die hohen Bits (die die 16- und 4-Stelle darstellen) in 2000 oder 2001 sind, HÄNGT von Endian-ness ab, aber die Tatsache bleibt, dass, welches Byte auch immer die gesetzten Bits enthält, das andere immer noch unbrauchbar ist, weil es Teil von ist
int
Speicherplatz des Typs.– Platin Azur
27. Dezember 2010 um 18:03 Uhr
@platinum Azure: Tut mir leid, ich konnte nicht verstehen, was du mit “16. und 4. Platz” meinst. Außerdem sage ich, dass, wenn ich dies tue: int a=20; printf(“%d”,* (char*)&a); Hängt die Ausgabe dann nicht von der Endianität ab, dh ob 20 bei 2000 oder 2001 gespeichert wird?
– Glücklicher Mittal
27. Dezember 2010 um 18:07 Uhr