2011-09-28 11 views
5

Wiele projektów C++ (np. Wiele bibliotek Boost) jest "połączonych tylko z nagłówkiem".Łączenie tylko nagłówków

Czy jest to również możliwe w przypadku zwykłego C? Jak umieścić kod źródłowy w nagłówkach? Czy są jakieś strony na ten temat?

+0

Robisz to dokładnie tak samo, jak w C++. Włączenie nagłówka jest funkcją preprocesora C. – avakar

+0

Ale masz wszystkie te funkcje statyczne i funkcje publiczne, myślę, że to nie takie proste. – Cartesius00

Odpowiedz

11

Streszczenie: Możesz, ale nie powinieneś.

C i C++ kod jest preprocesowany zanim zostanie skompilowany: wszystkie nagłówki są „wklejone” w plikach źródłowych, które je zawierają, rekurencyjnie. Jeśli zdefiniujesz funkcję w nagłówku i zostanie ona dołączona do dwóch plików C, otrzymasz dwie kopie w każdym pliku obiektów (naruszenie One Definition Rule).

Możesz tworzyć biblioteki C tylko z nagłówkiem, jeśli wszystkie twoje funkcje są oznaczone jako static, czyli niewidoczne poza jednostką tłumaczeniową. Ale oznacza to również, że otrzymasz kopię wszystkich funkcji statycznych w każdej jednostce tłumaczeniowej, która zawiera plik nagłówkowy.

W C++ jest nieco inaczej: funkcje inline nie są static, symbole emitowane przez kompilator są nadal widoczne przez linker, ale linker może odrzucić duplikaty zamiast rezygnować ("słabe" symbole).

Zapisywanie kodu C w nagłówkach nie jest idiotyczne, chyba że jest oparte na makrach (na przykład queue(3)). W C++ głównym powodem do zachowania kodu w nagłówkach są szablony, które mogą powodować tworzenie kodu dla różnych parametrów szablonu, co nie ma zastosowania do C.

+0

+1: Obejmuje prawie wszystkie podstawy, które myślę. –

4

Nie łączysz nagłówków.

W C++ nieco łatwiej jest napisać kod, który jest już lepszy w nagłówkach niż w osobno skompilowanych modułach, ponieważ szablony tego wymagają.

Ale można również użyć słowa kluczowego inline dla funkcji, które istnieją zarówno w języku C, jak i C++.

// Won't cause redefinition link errors, because of 6.7.4/5 
inline void foo(void) { 
    // ... 
} 

[c99: 6.7.4/5:] Funkcja zadeklarowaną inline funkcji specyfikacją jest funkcją rolki. Detektor funkcji może pojawić się więcej niż jeden raz; zachowanie jest takie samo, jak gdyby pojawiło się tylko raz. Wykonywanie funkcji inline sugeruje, że połączenia z funkcją powinny przebiegać tak szybko, jak to możliwe. Zakres, w jakim takie sugestie są skuteczne, jest zdefiniowany przez implementację.

Trochę utkniesz, jeśli chodzi o obiekty danych.


- W pewnym sensie.
- C99 na pewno. C89/C90 Muszę sprawdzić.

+0

Czy chodziło Ci o statyczne słowo kluczowe? Ponieważ inline jest tylko poleceniem dla kompilatora i może być całkowicie zignorowane. – Cartesius00

+0

@ James: Nie, miałem na myśli 'inline'. Chociaż 'inline' jest tylko podpowiedzią i kompilator nie musi fizycznie wstawiać funkcji, efekt, który ma on na powiązaniu funkcji, jest dobrze zdefiniowany i musi być obserwowany przez implementację. W przeciwnym razie, jak mógłbyś kiedykolwiek powiedzieć jakie powiązanie ma twoja funkcja 'inline'? –

+0

Och, widzę, jest inaczej w C kontra C++, prawda? – Cartesius00

4

doładowania sprawia, szablony intensywnego użytkowania i szablon meta-programowania, który nie może emulować (wszystkie, które łatwo) w C.

Ale można oczywiście oszukać poprzez deklaracje i kod w nagłówkach C którego #include ale to nie to samo. Powiedziałbym, "Kiedy w Rzymie ..." i program C zgodnie z konwencjami C z bibliotekami.

+0

Uważam, że "Kiedy w Rzymie ..." to świetna odpowiedź. Dziękuję :) – Cartesius00

+0

Cieszę się, że mogę pomóc. Możesz go również zaakceptować, pod warunkiem, że nadal będzie to najlepsza odpowiedź podczas sprawdzania. –

3

Tak, jest całkiem możliwe. Deklaruj wszystkie funkcje w nagłówkach i wszystkie jako static lub po prostu użyj pojedynczej jednostki kompilacji (tj. Tylko jednego pliku c) w swoich projektach.

Jako osobistą anegdotę znam wielu fizyków, którzy upierają się, że ta technika jest jedyną prawdziwą metodą programowania C. Jest to korzystne, ponieważ jest to wersja biednego mężczyzny z -fwhole-program, tj. Dokonuje optymalizacji w oparciu o wiedzę możliwe zachowanie funkcji. Jest to praktyczne, ponieważ nie musisz uczyć się o używaniu flag łącznika. To zły pomysł, ponieważ cały twój program musi być skompilowany jako całość i ponownie skompilowany z każdą drobną zmianą.

Osobiście, poleciłbym go lub przynajmniej skorzystam z static tylko dla kilku funkcji.

+0

Odpowiedź nie wskazuje na rażącą dziurę w tym podejściu. –

+0

@ TomalakGeret'kal: Które z jaskrawych dziur? – thiton

+0

'statyczny' daje ci kopie na TU. Naprawdę, dziury, o których wspominają wszystkie inne odpowiedzi. –