2012-04-09 25 views
7

Aktualnie studiuję na końcowym egzaminie z kursu CS i natknąłem się na mniejszy (być może poważny?) Problem dotyczący składni C++ #ifndef.#następująca składnia dla włączających strażników w C++

Szukałem w składni #infndef podczas używania go jako #include straży, a najbardziej w sieci wydaje się mówić:

#ifndef HEADER_H 
#define "header.h" 
... 
#endif 

Ale slajdy TUTORIAL moja klasa pokazują przykłady jak:

#ifndef __HEADER_H__ 
#define "header.h" 
... 
#endif 

Zastanawiam się, co (jeśli w ogóle) różnica między nimi. Egzamin najprawdopodobniej poprosi mnie o napisanie # strażnika, a ja wiem, że konwencjonalna mądrość polega właśnie na tym, co mówi prof/tutor, ale jeśli podczas kompilacji jest różnica, chciałbym to wiedzieć.

+5

Zobacz [tutaj] (http://stackoverflow.com/questions/228783), aby zapoznać się z zasadami, które łamie twój opiekun, i [tutaj] (http://stackoverflow.com/questions/3345159) dla przykład, co może pójść źle, jeśli je złamiesz. Uwzględnij także strażników * wewnątrz * nagłówka. –

+0

Tak się składa, że ​​kod źródłowy nie ma sensu: nie można "# define" literału literowego. Czy chodziło Ci o '#include 'header.h" '(oryginalne sformułowanie) lub' #define HEADER_H' (co zwykle znajduje się w nagłówku preambuły)? – Attila

Odpowiedz

17

Powszechnie stosowaną praktyką jest nie wpisywanie żadnego z nich i umieszczenie w nim pliku w pliku nagłówkowym, ponieważ redukuje on liczbę powtórzeń. np .:

header.h

#ifndef HEADER_H 
#define HEADER_H 

// Rest of header file contents go here 

#endif 

Dokładnie to, czego użyć jako nazwę makra jest w dół do konkretnego standardu kodowania. Istnieją jednak subtelne reguły w standardach C i C++, które uniemożliwiają korzystanie z identyfikatorów zaczynających się od podkreśleń, , więc powinieneś unikać __HEADER_H__, aby być po bezpiecznej stronie.

Warto również wspomnieć, że powinieneś wybrać coś, co raczej nie koliduje z niczym innym w bazie kodu. Na przykład, jeśli zdarzyło Ci się mieć zmienną o nazwie HEADER_H w innym miejscu (mało prawdopodobne, zdaję sobie z tego sprawę), to skończyłoby się na kilku irytujących błędach.


1. Zobacz np. sekcja 7.1.3 normy C99.

+1

... a jeśli nie jest to plik nagłówkowy implementacji, powinien unikać identyfikatorów zawierających podkreślenie, a następnie inne podkreślenie lub wielką literę. –

+0

@JerryCoffin: "zawierający" lub "począwszy od"? –

+0

Dla C, począwszy. Dla C++, zawierający podwójny znak podkreślenia, jest również verboten (ale podkreślenie i ograniczenie są dozwolone, o ile nie są na początku). –

1

Nie ma różnicy, jeśli nie użyjesz podkreślenia w nazwach zmiennych gdziekolwiek indziej, to tylko konwencja nazewnictwa.

Wystarczy umieścić coś wyjątkowego.

+4

Nieprawda. Nazwy zaczynające się od dwóch podkreśleń są zarezerwowane dla implementacji (przynajmniej w C99). –

+1

+1: Właściwie odpowiada na pytanie OP zamiast na "zwykły" sposób robienia rzeczy. –

+4

To nie tylko konwencja. Używanie identyfikatora zaczynającego się od '__' powoduje, że zachowanie twojego kodu jest niezdefiniowane. Implementacja (kompilator lub biblioteka standardowa) może dowolnie używać nazwy '__HEADER_H__' dla własnych celów; jeśli to zrobi, twoje własne użycie tego identyfikatora może oznaczać dosłownie * cokolwiek *. –

5

Nazwy zaczynające się od podwójnego podkreślenia są zarezerwowane dla implementacji, więc odradzam używanie __SOMETHING w twoich załącznikach. Spróbuj także wybrać nazwy, które sprawiają, że starcia są mało prawdopodobne. Wygląda więc na to, że tutoriale twojej klasy są błędne przynajmniej na dwa razy. Zobacz na przykład: humorous article.

0

Argumentem za umieszczeniem osłon włączających w pliku, który zawiera nagłówek, a nie w samym nagłówku, jest to, że jeśli plik został już dołączony, kompilator (konkretnie preprocesor) nie musi otwierać i czytać ponownie dołącz plik.

To jest słaby argument. W praktyce zaoszczędzony czas jest banalny, a potencjał błędu jest duży.

W przykładzie:

#ifndef HEADER_H 
#include "header.h" 
... 
#endif 

nie pokazują nam #define HEADER_H. Czy to gdzieś w header.h?Jeśli tak, to skąd wiadomo, że autor header.h wybrał użycie nazwy HEADER_H jako nazwy makra obsługującego zabezpieczenia? Co się stanie, jeśli później zmieni się coś innego?

Jeśli zdecydujesz się umieścić obejmują strażnika w tym pliku, należy zdefiniować makro również tam:

#ifndef HEADER_H 
#include "header.h" 
#define HEADER_H 
#endif 

Ale, jak inne odpowiedzi już powiedziałem, to dużo lepiej umieścić strażnik w nagłówku samego:

header.h:

#ifndef HEADER_H 
#define HEADER_H 
/* contents of header.h */ 
#endif 

a następnie obejmuje po prostu:

#include "header.h" 

i ma o jeden mniej informacji martwić się.