Das habe ich heute bei einem Interview angeboten.
%Vor% Mein Interviewer bestand darauf, dass c
und l
nicht garantiert an der gleichen Adresse beginnen. Daher sollte die Union geändert werden, um char c[sizeof(long)]
zu sagen und der Rückgabewert sollte in u.c[0] == 1
geändert werden.
Stimmt es, dass Mitglieder einer Gewerkschaft möglicherweise nicht an derselben Adresse beginnen?
Sie haben Recht damit, dass die "Mitglieder einer Gewerkschaft vielleicht an derselben Adresse beginnen". Der maßgebliche Teil des Standards ist (6.7.2.1 Abs. 13) :
Die Größe einer Union reicht aus, um die größten ihrer Mitglieder zu enthalten. Der Wert von höchstens einem der Mitglieder kann jederzeit in einem Union-Objekt gespeichert werden. Ein Zeiger auf ein Union-Objekt, das entsprechend konvertiert wird, zeigt auf jedes seiner Elemente (oder wenn ein Element ein Bit-Feld ist, dann auf die Einheit, in der es sich befindet) und umgekehrt.
Grundsätzlich ist eine Startadresse der Union garantiert die gleiche wie die Startadresse jedes seiner Mitglieder. Ich glaube (auf der Suche nach der Referenz), dass ein long
garantiert größer ist als ein char
. Wenn Sie dies annehmen, sollte Ihre Lösung gültig sein .
* Ich bin immer noch ein wenig unsicher, da es einige interessante Formulierungen rund um die Darstellung ganzzahliger und insbesondere vorzeichenbehafteter Integer-Typen gibt. Lesen Sie die Abschnitte 6.2.6.2 und 1 & amp; 2.
Ich war unsicher über die Mitglieder der Gewerkschaft, aber SO kam zu Hilfe .
Die Prüfung kann besser geschrieben werden als:
%Vor%Übrigens zeigt die C-FAQ beide Methoden: Wie kann ich feststellen, ob die Bytereihenfolge einer Maschine big-endian oder wenig ist? Endian?
Während Ihr Code wahrscheinlich in vielen Compilern funktioniert, hat der Interviewer Recht - wie man Felder in einer Union oder einer Struktur ausrichtet, liegt ganz bei dem Compiler und in diesem Fall könnte der Char entweder am "Anfang" oder am Ende platziert werden "Ende". Der Code des Interviewers lässt keinen Zweifel aufkommen und funktioniert garantiert.
Der Standard sagt, dass die Offsets für jedes Element in einer Union Implementierung definiert sind.
Wenn ein Wert in einem Member eines Objekts vom Union-Typ gespeichert wird, werden die Bytes des Objekts angezeigt Darstellung, die nicht diesem Mitglied entspricht, aber anderen Mitgliedern entspricht nimm unspezifizierte Werte. ISO / IEC 9899: 1999 Darstellung der Typen 6.5.6.2, Abs. 7 (pdf-Datei )
Daher ist es Sache des Compilers, zu wählen, wo das Zeichen innerhalb der Union relativ zum Long platziert werden soll - sie haben nicht garantiert dieselbe Adresse.
Ich habe eine Frage dazu ...
Wie ist
?u.c [0] == alles
gültig gegeben:
%Vor%Wie funktioniert [0] auf einem Zeichen?
Scheint mir, es wäre äquivalent zu: (* u.c + 0) == irgendwas, was, naja, Mist wäre, wenn man den Wert von u.c betrachtet, der wie ein Zeiger behandelt wird, wäre Mist.
(Außer vielleicht, wie es mir jetzt einfällt, aß irgendein HTML-Mist-Code ein kaufmännisches Und-Zeichen in der ursprünglichen Frage ...)
Obwohl der Interviewer korrekt ist und dies nicht garantiert ist, funktioniert auch keine der anderen Antworten, da ein Dereferenzieren eines Zeigers nach dem Umwandeln in einen anderen Typ zu undefiniertem Verhalten führt.
In der Praxis wird dies (und die anderen Antworten) immer funktionieren, da alle Compiler transparent zwischen Pointer-zu-Union- und Pointer-zu-Union-Elementen umwandeln können - viel alter Code wird nicht funktionieren, wenn sie funktionieren nicht.
Ein noch nicht erwähnter Punkt ist, dass der Standard explizit die Möglichkeit zulässt, dass Integer-Repräsentationen Padding-Bits enthalten können. Persönlich wünschte ich, das Standardkomitee würde einem Programm eine einfache Möglichkeit geben, bestimmte erwartete Verhaltensweisen zu spezifizieren, und verlangen, dass jeder Compiler diese Spezifikationen entweder respektieren oder die Kompilierung ablehnen muss; Code, der mit einer "Integers darf keine Padding-Bits" -Spezifikation hat, wäre dann berechtigt, davon auszugehen, dass dies der Fall ist.
Wie dem auch sei, wäre es vollkommen legitim (wenn auch ungerade), dass eine Implementierung 35-Bit long
-Werte als vier 9-Bit-Zeichen im Big-Endian-Format speichert, aber das LSB des ersten Bytes als a Paritätsbit. Bei einer solchen Implementierung könnte das Speichern von 1
in long
dazu führen, dass die Parität des gesamten Worts ungerade wird, was die Implementierung zwingt, 1
in das Paritätsbit zu speichern.
Ein solches Verhalten wäre zwar seltsam, aber wenn Architekturen, die Padding verwenden, ausreichend auffällig sind, um explizite Bestimmungen im Standard zu rechtfertigen, kann Code, der auf solchen Architekturen bricht, nicht wirklich als "portabel" angesehen werden. p>
Der Code, der union
verwendet, sollte auf allen Architekturen korrekt funktionieren, die einfach als "big-endian" oder "little-endian" bezeichnet werden können und keine Füllbits verwenden. Es wäre auf einigen anderen Architekturen bedeutungslos (und in der Tat könnten die Begriffe "big-endian" und "little-endian" ebenfalls bedeutungslos sein).
Tags und Links c endianness