Ich verstehe grob die Regeln mit dem, was # include mit dem C Präprozessor macht, aber ich verstehe es nicht vollständig. Im Moment habe ich zwei Header-Dateien, Move.h und Board.h, die beide ihren jeweiligen Typ eingeben (Move und Board). In beiden Header-Dateien muss ich auf den Typ verweisen, der in der anderen Header-Datei definiert ist.
Im Moment habe ich # Move.h in Board.h enthalten und # Board.h in Move.h. Wenn ich jedoch kompiliere, kippt gcc aus und gibt mir eine lange (was wie unendlich rekursiv aussieht) Fehlermeldung zwischen Move.h und Board.h.
Wie schließe ich diese Dateien so ein, dass ich sie nicht rekursiv einschließe?
Sie müssen in Vorwärtsdeklarationen suchen , Sie haben endlose Schleifen von Includes erstellt, Vorwärtsdeklarationen sind die richtige Lösung.
Hier ist ein Beispiel:
Verschieben.h
%Vor%Board.h
%Vor%main.c
%Vor%Hinweis: Wenn Sie ein "Board" erstellen, müssen Sie so etwas tun (es gibt ein paar Möglichkeiten, hier ein Beispiel):
%Vor%Wie so:
%Vor% Auf diese Weise kann Board.h
ohne Abhängigkeit von move.h
kompiliert werden, und Sie können board.h
von move.h
einfügen, um den Inhalt dort verfügbar zu machen.
Zunächst scheint es, dass Wächter in Ihren .h
-Dateien nicht enthalten sind, sodass Sie sie rekursiv einschließen. Das ist schlecht.
Zweitens können Sie eine Vorwärtsdeklaration durchführen. In Move.h
:
In Board.h
:
Beachten Sie, dass diese Methode nicht funktioniert, wenn Sie in beiden Dateien struct Move
und struct Board
-Objekte deklarieren müssen (anstatt Zeiger auf einen von ihnen). Dies liegt daran, dass einer der Typen zum Zeitpunkt des Parsens einer der Dateien ein unvollständiger Typ ist ( struct Move
im obigen Beispiel).
Wenn Sie also die Typen in beiden Dateien verwenden müssen, müssen Sie die Typdefinitionen trennen: haben Header-Dateien, die struct Move
und struct Board
definieren, und nichts anderes (etwas wie mein Beispiel oben) und dann eine andere Headerdatei verwenden, die sowohl auf struct Move
als auch auf struct Board
verweist.
Natürlich können Sie nicht struct Move
contain eine struct Board
und struct Board
gleichzeitig struct Move
enthalten - das wird eine unendliche Rekursion sein, und die Strukturgrößen sind auch unendlich!
Sie müssen zuerst einen von ihnen haben. Machen Sie eine Vorwärtsdecl in einer von ihnen und haben Sie diese für zum Beispiel
%Vor%könnte Teil der board.h-Datei sein.
und
%Vor%könnte Teil der Datei move.h sein
Dann könnten Sie sie in beliebiger Reihenfolge hinzufügen.
Bearbeiten Wie in den Kommentaren darauf hingewiesen wurde ... nahm ich die Verwendung des typedef-Konstrukts für die Board-Struktur wie folgt an:
%Vor%Da ich noch nie jemanden gesehen habe, der Strukturen in C ohne Typdef verwendet, habe ich diese Annahme gemacht ... vielleicht haben sich die Dinge seit der letzten Kodierung in C geändert (yikies .... es war vor 15 Jahren)
Circular Abhängigkeiten sind ein Schmerz in den Arsch und sollte beseitigt werden, wo immer möglich. Zusätzlich zu den bisher gegebenen Vorwärtsdeklarationsvorschlägen (Aloks ist das beste Beispiel) möchte ich einen weiteren Vorschlag in die Arbeit werfen: die gegenseitige Abhängigkeit zwischen Board und Move durch Einführung eines dritten Typs (nennen wir es BoardMoveAssoc zur Veranschaulichung; Ich bin mir sicher, dass du einen weniger bescheuerten Namen finden kannst):
%Vor%Nach diesem Schema müssen Board und Move nichts voneinander wissen; Alle Verknüpfungen zwischen den beiden werden vom Typ BoardMoveAssoc verwaltet. Die genaue Struktur hängt davon ab, wie Move und Board zusammenhängen sollen. Wenn z. B. mehrere Züge einer einzelnen Karte zugeordnet sind, sieht die Struktur möglicherweise eher wie
aus %Vor%Auf diese Weise müssen Sie sich nicht um Vorwärtsdeklarationen oder unvollständige Typen kümmern. Sie führen einen dritten Typ in den Mix ein, aber ich glaube, dass dies leichter zu verstehen und zu pflegen ist.
Von K & amp; R Die C-Programmiersprache (S. 91 "Bedingte Aufnahme" in meiner Kopie), mit einigen Verbesserungen für Sie:
%Vor%und dasselbe für Move.h
Auf diese Weise wird, sobald ein Header einmal eingeschlossen wurde, dieser nicht erneut eingefügt, da der Name 'BOARD_H' bereits für den Präprozessor definiert wurde.
Tags und Links include gcc c-preprocessor