Czy "inline" bez "static" lub "extern" jest kiedykolwiek przydatny w C99?
Kiedy próbuję zbudować ten kod
inline void f() {}
int main()
{
f();
}
Użycie wiersza poleceń
gcc -std=c99 -o a a.c
I get a linker error(undefined reference to f
). Błąd znika, jeśli używam static inline
lub extern inline
zamiast tylko inline
, lub jeśli kompiluję z -O
(więc funkcja jest faktycznie inlined).
Zachowanie to wydaje się być zdefiniowane w pkt 6.7.4 (6) normy C99:
Jeśli wszystkie deklaracje zakresu pliku dla funkcji w jednostce tłumaczeniowej zawierają
inline
Specyfikacja funkcji bezextern
, wtedy definicja w tej jednostce translacji jest definicją inline. Definicja inline nie dostarcza definicji zewnętrznej dla funkcji i nie zabrania definicji zewnętrznej w innej jednostce tłumaczeniowej. Definicja inline stanowi alternatywę dla definicji zewnętrznej, której tłumacz może użyć do implementacji dowolnego wywołania funkcji w tej samej jednostce tłumaczeniowej. Nie jest określone, czy wywołanie funkcji używa definicji inline lub definicji zewnętrznej.
Jeśli dobrze to Rozumiem, Jednostka kompilacji z funkcją zdefiniowaną inline
jak w powyższym przykładzie kompiluje się konsekwentnie tylko wtedy, gdy istnieje również funkcja zewnętrzna o tej samej nazwie, i nigdy nie wiem, czy wywołana jest moja własna funkcja lub funkcja zewnętrzna.
inline
bez static
lub extern
? Coś przeoczyłem?
Podsumowanie odpowiedzi
Oczywiście, że coś przeoczyłem, a zachowanie nie jest głupie. :)
Jak wyjaśnia Nemo , ideą jest umieszczenie definicji funkcji
inline void f() {}
W pliku nagłówkowym i tylko deklaracja
extern inline void f();
W odpowiednim .plik C. Tylko deklaracja extern
uruchamia generowanie widocznego na zewnątrz kodu binarnego. I rzeczywiście nie ma zastosowania inline
wplik c -- jest przydatny tylko w nagłówki.
Jak wyjaśnia uzasadnienie Komitetu C99 cytowane w odpowiedzi Jonathana, inline
dotyczy optymalizacji kompilatora, która wymaga, aby definicja funkcji była widoczna w miejscu wywołania. Można to osiągnąć tylko poprzez umieszczenie definicji w nagłówku i oczywiście definicja w nagłówku nie może emitować kodu za każdym razem, gdy jest widziana przez kompilator. Ponieważ jednak kompilator nie jest zmuszony do wbudowania funkcji, definicja zewnętrzna musi istnieć gdzieś.
3 answers
Faktycznie ta doskonała odpowiedź również odpowiada na twoje pytanie, myślę:
Chodzi o to, że "inline" może być użyty w pliku nagłówkowym, a następnie "extern inline" w pliku .plik C. "extern inline" jest po prostu tym, jak instruujesz kompilator, który plik obiektowy powinien zawierać (zewnętrznie widoczny) wygenerowany kod.
[update, do opracowania]
Wydaje mi się, że nie ma zastosowania "inline" (bez "static" lub "extern") w a .plik C. Ale w nagłówku plik ma sens i wymaga odpowiedniej deklaracji" extern inline " w niektórych .plik c do generowania samodzielnego kodu.
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
2017-05-23 12:02:41
Od samej normy (ISO/IEC 9899:1999):
Dodatek J. 2 Nieokreślone Zachowanie
- ...
- funkcja z powiązaniem zewnętrznym jest deklarowana za pomocą specyfikacji funkcji
inline
, ale nie jest również zdefiniowana w tej samej jednostce translacyjnej (6.7.4).- ...
Komitet C99 napisał uzasadnienie i mówi:
6.7.4 specyfikatory funkcji
nowa funkcja C99: słowo kluczowe
inline
, zaadaptowane z C++, jest specyfikatorem funkcji , który może być używany tylko w deklaracjach funkcji. Jest przydatny do optymalizacji programów, które wymagają definicja funkcji, która ma być widoczna w miejscu wywołania. (Należy pamiętać, że Standard nie próbuje określić charakteru tych optymalizacji.)Widoczność jest zapewniona, jeśli funkcja ma połączenie wewnętrzne, lub jeśli ma połączenie zewnętrzne i wywołanie jest w tej samej jednostce tłumaczeniowej co definicja zewnętrzna. W takich przypadkach obecność
inline
Słowo kluczowe w deklaracji lub definicji funkcji nie ma wpływu poza wskazaniem preferencja, że wywołania tej funkcji powinny być zoptymalizowane w stosunku do wywołań innych funkcji zadeklarowanych bez słowa kluczowegoinline
.Widoczność jest problemem dla wywołania funkcji z linkiem zewnętrznym, gdzie wywołanie jest w inna jednostka translacji od definicji funkcji. W tym przypadku
inline
słowo kluczowe pozwala jednostce tłumaczeniowej zawierającej wywołanie również zawierać lokalną lub inline definicję funkcja.Program może zawierać jednostkę tłumaczenia z zewnętrzną definicją, jednostkę tłumaczenia z inline definition, oraz jednostka translacji z deklaracją, ale bez definicji funkcji. Połączenia w tym drugim tłumaczeniu jednostka będzie używać definicji zewnętrznej jak zwykle.
Inline definicja funkcji jest uważana za inna definicja niż zewnętrzna definicja. Jeśli wywołanie jakiejś funkcji {[7] } z linkiem zewnętrznym występuje, gdy inline definicja jest widoczna, zachowanie jest takie samo, jak gdyby wywołanie zostało wykonane do innej funkcji, powiedzmy
__func
, z wewnętrznym połączeniem. Zgodny program nie może zależeć od tego, która funkcja jest dzwoniłem. Jest to model inline w standardzie.Zgodny program nie może polegać na implementacji wykorzystującej definicję inline, ani nie może polega na realizacja z wykorzystaniem definicji zewnętrznej. Adres funkcji jest zawsze adresem odpowiadającym definicji zewnętrznej, ale gdy adres ten jest używany do wywołania funkcja, można użyć definicji inline. Dlatego poniższy przykład może nie zachowuj się zgodnie z oczekiwaniami.
inline const char *saddr(void) { static const char name[] = "saddr"; return name; } int compare_name(void) { return saddr() == saddr(); // unspecified behavior }
Ponieważ implementacja może użyć definicji inline dla jednego z wywołań do
saddr
i użyć zewnętrzna definicja drugiej, operacja równości nie jest gwarantowana do oceny do 1 (prawda). Pokazuje to, że obiekty statyczne zdefiniowane w definicji inline różnią się od swoich odpowiedni obiekt w definicji zewnętrznej. Motywowało to ograniczenie nawet definiowanie obiektu nie -const
tego typu.Inlining został dodany do standardu w taki sposób, że można go zaimplementować za pomocą istniejącego linkera technologii, a podzbiór C99 jest kompatybilny z C++. Udało się to osiągnąć, wymagając dokładnie jednego tłumaczenia Jednostka zawierająca definicję funkcji inline be określona jako ta, która dostarcza zewnętrznej definicji funkcji. Ponieważ to Specyfikacja składa się po prostu z deklaracji, która albo nie zawiera słowa kluczowego
inline
, albo zawiera zarównoinline
, jak iextern
, zostanie również zaakceptowany przez tłumacza C++.Inlining w C99 rozszerza specyfikację C++ na dwa sposoby. Po pierwsze, jeśli funkcja jest zadeklarowana
inline
w jednej jednostce tłumaczeniowej nie musi być deklarowanainline
w każda inna jednostka tłumaczeniowa. Pozwala to na przykład na funkcję biblioteki, która ma być wbudowana w bibliotekę, ale dostępna tylko przez zewnętrzną definicję gdzie indziej. Alternatywą użycia funkcji wrapper dla funkcja zewnętrzna wymaga dodatkowej nazwy; może również mieć negatywny wpływ na wydajność jeśli Tłumacz nie wykonuje podstawienia w wierszu.Po Drugie, wymóg, aby wszystkie definicje funkcji inline były "dokładnie takie same" jest zastąpione wymogiem, że zachowanie programu nie powinno zależeć od tego, czy wywołanie jest zaimplementowane z widoczną definicją inline lub definicją zewnętrzną funkcji. Pozwala to na wyspecjalizowanie definicji inline do jej użycia w ramach określonej jednostki tłumaczeniowej. Na przykład, zewnętrzna definicja funkcji bibliotecznej może zawierać pewne walidacje argumentów, które nie są potrzebne do wywołań z innych funkcji w tej samej bibliotece. Te rozszerzenia oferują niektórych zalet; oraz programistów, którzy troszczą się o kompatybilność może po prostu przestrzegać surowszych zasad C++.
Zauważ, że nie jest to odpowiednie dla implementacji, aby zapewnić inline definicje standardu funkcje biblioteki w standardowych nagłówkach, ponieważ może to złamać niektóre starsze kody, które ponownie deklarują standardowe funkcje biblioteki po włączeniu ich nagłówków. Słowo kluczowe
inline
to przeznaczone wyłącznie do zapewnienia użytkownikom przenośnego sposobu sugerowania funkcje. Ponieważ standardowe nagłówki nie muszą być przenośne, implementacje mają inne opcje w linii:#define abs(x) __builtin_abs(x)
Lub inne przenośne mechanizmy do wbudowywania standardowych funkcji bibliotecznych.
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
2011-06-11 06:11:06
> I get a linker error (undefined reference to f
)
Działa tutaj: Linux x86-64, GCC 4.1.2. Może to być błąd w Twoim kompilatorze; nie widzę w cytowanym akapicie niczego ze standardu, który zabraniałby danego programu. Zwróć uwagę na użycie if zamiast MFF.
Definicja inline zapewnia alternatywę dla definicji zewnętrznej, której Tłumacz może użyć do zaimplementowania dowolnego wywołania funkcji w ta sama jednostka tłumaczeniowa.
Tak więc, jeśli znasz zachowanie funkcji f
i chcesz wywołać ją w ciasnej pętli, możesz skopiować i wkleić jej definicję do modułu, aby zapobiec wywołaniu funkcji; lub, możesz podać definicję, która dla celów bieżącego modułu jest równoważna(ale pomija walidację wejściową lub jakąkolwiek optymalizację możesz sobie wyobrazić). Kompilator ma jednak możliwość optymalizacji rozmiaru programu.
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
2011-06-10 23:26:29