2010-05-30 5 views
13

Was betrifft Best Practice in Bezug auf die folgenden "Muster"?Best-Practice auf C-Header-Dateien mit #ifndef #define #endif

#ifndef BLAFOO_H 
#define BLAFOO_H 
/* ... 
* ... 
*/ 
#endif /* BLAFOO_H */ 

wie soll ich die Überschrift in der #define Direktive benennen? Ich habe alles von besagtem BLAFOO_H zu __BLAFOO_H zu _BLAFOO_H_ usw. gesehen.

+8

FYI, das * Muster * ist ein ** umfassen genannt bewachen**. –

Antwort

1

Es ist nicht wirklich wichtig, solange es wahrscheinlich nirgendwo anders verwendet wird. Ich gehe normalerweise mit etwas wie BLAFOO_H_INCLUDED.

22

Benennen Sie sie BLAFOO_H (ich persönlich benutze BLAFOO_H_, wobei BLAFOO der Header-Dateiname ist).

Stellen Sie sicher, dass Ihr BLAFOO nicht mit anderen Dateien/Bibliotheken/etc. Kollidiert. Du verwendest z.B. Lassen Sie Ihren Projekt- und/oder Modulnamen Teil dieses Namens sein.

Bezeichner, die mit einem _ beginnen, sind für die Implementierung/den Compiler reserviert, also verwenden Sie das nicht.

+5

+1 für die Erwähnung, dass Kennungen, die mit _ beginnen, für die Implementierung reserviert sind –

3

Die einzige wirkliche Anforderung ist, dass es keinen Konflikt mit einem anderen Projekt gibt, das denselben Namen für seine Datei verwendet. Bei allen Projekten, die ich gesehen habe, quantifiziert es normalerweise den Namespace (oder den Ordner, in dem sich die Datei für C befindet) vollständig mit dem Projektnamen. Manchmal enthält es auch das Datum, an dem die Datei erstellt wurde.

Also, wenn Sie auf Projekt ABC in Ordner DEF heute arbeiten, dann könnten Sie tun:

#ifndef ABC_DEF_BLAFOO_H_05_30_2010 

Und das ist sehr unwahrscheinlich, dass Konflikte mit irgendetwas.

5

Ich benutze ein UUID das ist meine Garantie, dass #define nicht mit anderen kollidiert. Ich habe es irgendwo gesehen und beschlossen, es auch zu benutzen.

Mein Muster ist wie folgt: __<filename>_H_<uuid>__,

zB. #define __TYPES_H_79057761_16D6_478A_BFBC_BBF17BD3E9B9__ für eine Datei mit dem Namen types.h

+0

Wie generiert man eine UUID? Verwenden Sie ein automatisiertes Tool oder eine Funktion in Ihrer IDE? –

+2

Ich denke auch, eine GUID zu verwenden, ist eine gute Idee, aber ein paar Kommentare - streng genommen sollten Sie nicht das Präfix "__" verwenden, da es für die Implementierung reserviert ist (obwohl es wenig Chance für einen Konflikt mit der GUID gibt). Außerdem gibt es eine gute Chance, dass andere in Ihrem Team es nicht mögen - zumindest habe ich das gefunden. In dieser Situation dränge ich es nicht, da ich mich nicht an eine Situation erinnern kann, in der ein Wächterkonflikt tatsächlich ein Problem verursacht hat. –

+0

@Thomas - Visual Studio (und/oder das Windows SDK) stellt unter Windows das Befehlszeilenprogramm 'uuidgen' und das GUI-Tool' guidgen' zur Verfügung. Ich bin mir sicher, dass es ähnliche Tools für Unix-Systeme gibt. –

2

Wie bei anderen C-style Fragen, einfach konsistent sein. Es gibt keine Möglichkeit, dass Sie den Namespace jeder Bibliothek kennen, die jemand in Zukunft mit Ihrem Programm verknüpfen könnte. Warum? Viele von ihnen wurden noch nicht geschrieben :)

Als solche ist es keine Frage der Wächter, es ist eine Frage, was man den Header an erster Stelle nennen.

Ich könnte mit ein paar coole neue String-Utilities, und nennen Sie die Überschrift streusel. Das ist eine schlechte Idee, denn (sicherlich) hat jemand anderes coole neue String-Utilities gefunden und den Header gleich benannt.

So nenne ich mein post_strutils.h und:

#ifndef POST_STRUTILS_H 
#define POST_STRUTILS_H 
/* code */ 
#endif 

ich selbst es post_str_utils.h nennen können und definieren die Wachen angemessen sind, weil ich weiß, dass ich eine sehr häufige Nachnamen haben. Einen Namensraum zu finden ist manchmal schwierig. Einfach mit einem bietet keine Garantie, dass jemand anderes eine Suche vor der Freigabe von etwas in die Wildnis durchgeführt hat. Sei so einzigartig wie möglich.

Je nachdem, wo jemand seinen Compiler anweist, nach Kopfzeilen zu suchen, kommen nicht nur Namespace-Konflikte ins Spiel, sondern auch die Dateinamen. Geben Sie Ihr Bestes, um den Header eindeutig zu benennen, und schreiben Sie dann den Include-Guard, um ihn anzupassen. Jemand könnte wollen, #error, wenn die Überschrift mehrfach enthalten ist, wenn nur #include Direktiven zu schneiden, die nicht benötigt werden, mit einer UUID Art macht dies so verwirrend, da es nicht übereinstimmt (oder sogar ähneln) den Dateinamen des Headers in Frage. Es macht auch grep/awk (oder ähnliche) powered Lint-Skripte schwieriger zu schreiben.

Ich sage nicht, dass Sie jede Bibliothek/jedes Modul nach sich selbst benennen sollten, aber achten Sie darauf, dass die Namen der öffentlichen Header-Dateien eindeutig sind. Eine schnelle Konferenz mit einer Suchmaschine wird Ihnen sagen, ob Sie auf einen unbenutzten Namespace treffen. Bitte lassen Sie die Include-Wachen mit der Kopfzeile übereinstimmen (oder zumindest sehr ähnlich). Auch hier wird Konsistenz hoch gelobt. Von Ihrem Beispiel, würde ich erwarten:

int blahfoo_init(void); 
double blahfoo_getval(blahfoo_t *blah); 

Wenn Sie die Mühe, einen eindeutigen Namespace zu finden, zu gehen, sollten Sie es verwenden :)

+0

+1 für "Namespace" Präfix –