Gdzie umieścić instrukcje, nagłówek lub źródło?

Czy powinienem umieścić includes w pliku nagłówkowym czy w pliku źródłowym? Jeśli plik nagłówka zawiera instrukcje include, to jeśli dołączę ten plik nagłówka do mojego źródła, to czy mój plik źródłowy będzie zawierał wszystkie dołączone pliki, które były w moim nagłówku? A może powinienem tylko umieścić je w moim pliku źródłowym?

Author: Paul Roub, 2010-10-15

9 answers

Umieść includes w nagłówku tylko wtedy, gdy sam nagłówek ich potrzebuje.

Przykłady:

  • Twoja funkcja zwraca typ size_t. Następnie #include <stddef.h> w pliku nagłówka .
  • Twoja funkcja używa strlen. Następnie #include <string.h> w pliku źródłowym .
 105
Author: schot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 15:01:12

Przez lata było sporo nieporozumień w tej sprawie. W pewnym momencie tradycyjne było to, że nagłówek tylko deklaruje, co było w jakimkolwiek module, z którym był związany, więc wiele nagłówków miało określone wymagania, że #include określony zestaw nagłówków (w określonej kolejności). Niektórzy niezwykle tradycyjni Programiści C nadal stosują ten model (religijnie, przynajmniej w niektórych przypadkach).

Ostatnio nastąpił ruch w kierunku samodzielności większości nagłówków. Jeśli ten nagłówek wymaga czegoś innego, sam nagłówek obsługuje to, zapewniając, że wszystko, czego potrzebuje, jest włączone(we właściwej kolejności, jeśli są problemy z porządkowaniem). Osobiście wolę to-szczególnie, gdy kolejność nagłówków może być ważna, rozwiązuje problem raz, zamiast wymagać od wszystkich, którzy go używają, aby rozwiązać problem ponownie.

Zauważ, że większość nagłówków powinna zawierać tylko deklaracje. Oznacza to, że dodanie niepotrzebnego nagłówka nie powinno (normalnie) mieć żadnego efektu na twój ostateczny plik wykonywalny. Najgorsze, co się dzieje, to to, że spowalnia kompilację.

 23
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:58:08

Twoje #include powinny być plikami nagłówkowymi, a każdy plik (źródło lub nagłówek) powinien #include pliki nagłówkowe, których potrzebuje. Pliki nagłówkowe powinny #include być niezbędnymi minimalnymi plikami nagłówkowymi i plikami źródłowymi, choć nie jest to tak ważne dla plików źródłowych.

Plik źródłowy będzie zawierał Nagłówki #includes, oraz nagłówki #include, i tak dalej, aż do maksymalnej głębokości zagnieżdżania. Dlatego nie chcesz zbędnych #include s w plikach nagłówkowych: mogą one spowodować, że plik źródłowy będzie zawierał wiele plików nagłówkowych może nie być potrzebnych, spowalniając kompilację.

Oznacza to, że jest całkowicie możliwe, że pliki nagłówkowe mogą być dołączane dwa razy, co może być problemem. Tradycyjną metodą jest umieszczanie "include guards" w plikach nagłówkowych, takich jak ta dla pliku foo.h:

#ifndef INCLUDE_FOO_H
#define INCLUDE_FOO_H
/* everything in header goes here */
#endif
 10
Author: David Thornley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:56:57

Jeśli plik nagłówkowy a #includes pliki nagłówkowe B I C, to każdy plik źródłowy, który #includes A otrzyma również B I C #included. Pre-procesor dosłownie wykonuje zastępowanie tekstu: gdziekolwiek znajdzie tekst z napisem #include <foo.h> zastępuje go tekstem pliku foo.h.

Istnieją różne opinie na temat tego, czy należy umieścić #includes w nagłówkach, czy w plikach źródłowych. Osobiście wolę domyślnie umieścić wszystkie #includes w pliku źródłowym, ale wszystkie pliki nagłówkowe, które nie mogą się skompilować bez innych warunków wstępnych nagłówki powinny #include same te nagłówki.

I każdy plik nagłówkowy powinien zawierać zabezpieczenie include, aby zapobiec jego wielokrotnemu dołączaniu.

 4
Author: Vicky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:55:39

W niektórych środowiskach kompilacja będzie najszybsza, jeśli zawiera tylko potrzebne pliki nagłówkowe. W innych środowiskach kompilacja będzie zoptymalizowana, jeśli wszystkie pliki źródłowe będą mogły używać tej samej podstawowej kolekcji nagłówków (niektóre pliki mogą mieć dodatkowe nagłówki poza wspólnym podzbiorem). Idealnie, nagłówki powinny być skonstruowane tak, aby wiele operacji # include nie miało żadnego wpływu. Może być dobrze, aby otaczać polecenia #include sprawdzaniem include-guard pliku, który ma być dołączony, chociaż to tworzy zależność od formatu tego strażnika. Ponadto, w zależności od zachowania buforowania plików systemu, niepotrzebne # include, którego cel kończy się całkowitym # ifdef ' em, może nie potrwać długo.

Kolejną rzeczą do rozważenia jest to, że jeśli funkcja przyjmuje wskaźnik do struktury, można zapisać prototyp jako

void foo(struct BAR_s *bar);

Bez definicji BAR_s musi być w zakresie. Bardzo poręczne podejście do unikania niepotrzebnych obejmuje.

PS-w wielu moich projekty, będzie plik, który, jak się oczekuje, każdy moduł będzie zawierał#, zawierający takie rzeczy jak typedefs dla wielkości całkowitych i kilka wspólnych struktur i związków [np.
typedef union {
  unsigned long l;
  unsigned short lw[2];
  unsigned char lb[4];
} U_QUAD;

(tak, Wiem, że byłbym w tarapatach, gdybym przeniósł się na architekturę big-endian, ale ponieważ mój kompilator nie zezwala na anonimowe struktury w związkach, użycie nazwanych identyfikatorów dla bajtów w Unii wymagałoby dostępu do nich jako theUnion.b.b1 itd. co wydaje się dość denerwujące.

 4
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 15:55:19

Twórz wszystkie swoje pliki tak, aby mogły być budowane tylko za pomocą tego, co zawierają. Jeśli nie potrzebujesz nagłówka, usuń go. W dużym projekcie, jeśli nie utrzymasz tej dyscypliny, zostawiasz się otwartym na łamanie całej kompilacji, gdy ktoś usunie include z pliku nagłówkowego, który jest używany przez konsumenta tego pliku, a nawet przez nagłówek.

 3
Author: rerun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:59:24

Podejście, do którego ewoluowałem przez ponad dwadzieścia lat jest takie;

Rozważ bibliotekę.

Istnieje wiele plików C, jeden wewnętrzny plik H i jeden zewnętrzny plik H. Pliki C zawierają wewnętrzny plik H. Wewnętrzny plik H zawiera zewnętrzny plik H.

Widzisz, że z kompilatorów POV, ponieważ kompiluje plik C, istnieje hierarchia;

Zewnętrzny -> wewnętrzny - > kod C

Jest to prawidłowe uporządkowanie, ponieważ to, co zewnętrzne, jest wszystkim a osoby trzecie muszą korzystać z biblioteki. To, co jest wewnętrzne, jest wymagane do skompilowania kodu C.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 15:01:16

Twój plik źródłowy będzie zawierał instrukcje include, jeśli umieścisz je w nagłówku. Jednak w niektórych przypadkach lepiej byłoby umieścić je w pliku źródłowym.

Pamiętaj, że jeśli umieścisz ten nagłówek w innych źródłach, oni również otrzymają includes z nagłówka, co nie zawsze jest pożądane. Należy zawrzeć rzeczy tylko tam, gdzie jest używany.

 1
Author: Splashdust,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:54:30

W nagłówku należy umieszczać tylko pliki, które trzeba zadeklarować stałe i deklaracje funkcji. Technicznie, te elementy będą również zawarte w Twoim pliku źródłowym, ale dla jasności, powinieneś zawierać w każdym Pliku tylko te pliki, których faktycznie potrzebujesz. Powinieneś również chronić je w nagłówku przed wielokrotnym włączeniem w ten sposób:

#ifndef NAME_OF_HEADER_H
#define NAME_OF_HEADER_H

...definition of header file...

#endif

Zapobiega to wielokrotnemu dołączaniu nagłówka, co powoduje błąd kompilatora.

 1
Author: JRam930,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:59:12