Hier ist eine Interviewfrage, die ich in einem Forum gesehen habe. Ich habe versucht herauszufinden, wie es funktioniert, aber ich verstehe es nicht ganz. Könnte jemand erklären, wie es funktioniert?
F: Geben Sie einen Zeiger auf Element a innerhalb einer Struktur ein, schreiben Sie eine Routine, die einen Zeiger auf die Struktur zurückgibt.
%Vor%Die Antwort ist:
%Vor%Wie funktioniert es?
Die Grundgleichung hier (alle Arithmetik in Bytes) ist
%Vor% Gegeben der Typ von s
, ein einzelner Compiler und eine einzelne Zielmaschine, haben sie den Byte-Offset von a
bestimmt - er ist für jede Struktur vom Typ s gleich.
Sie erhalten die linke Seite und Ihr Interviewer hat Sie gebeten, s
wiederherzustellen. Sie können dies tun, indem Sie eine neue Gleichung erhalten; subtrahiere den Byte-Offset von beiden Seiten:
In dem Problem ist die Adresse von s->a
, aber Sie müssen den Byte-Offset herausfinden. Dazu verwenden Sie die ursprüngliche Gleichung erneut mit s
auf Null gesetzt:
Die linke Seite in C ist wie folgt aufgebaut:
%Vor%Letzte Schritte:
a_ptr
in char *
umgewandelt. struct s *
umgewandelt. Nachtrag: Wie Eli Bendersky betont, sollten Sie versuchen, Situationen zu vermeiden, in denen dieser Code notwendig wäre. Es gibt fast immer einen besseren Weg.
Die Antwort ist: es tut es nicht. Es funktioniert nicht, auch wenn es auf den ersten Blick zu "funktionieren" scheint. Die "Antwort" versucht, einen Null-Zeiger zu dereferenzieren, was zu undefiniertem Verhalten führt. Also, es sei denn, Ihre Idee von "arbeiten" umfasst undefiniertes Verhalten, funktioniert diese Antwort nicht.
Es gibt mehr Probleme mit dieser Lösung, außer dem Versuch, den Nullpunkt zu ignorieren (obwohl das alleine vollkommen ausreicht, um diese "Antwort" auf den Mülleimer zu werfen). Ein weiteres Problem ist, dass das Ergebnis von (struct s*) 0
ein Nullzeiger von struct s *
type ist. Die Sprache gibt keine Garantien über den tatsächlichen physikalischen Wert eines Nullzeigers. Es könnte leicht etwas wie 0xBAADFOOD
sein, was die beabsichtigte Funktionalität der "Antwort" sofort zunichte machen würde.
Die richtige Implementierung der implizierten Technik würde das Standard-Makro offsetof
beinhalten (bereits vorgeschlagen in Nyan's Antwort, aber ich werde es noch einmal wiederholen)