6.7.4 Specyfikatory funkcji
Nowością C99:inline słów kluczowych, zaadaptowany z C ++, to funkcja-specifier , które mogą być wykorzystane tylko w deklaracji funkcji. Jest to przydatne w przypadku optymalizacji programów, które wymagają, aby definicja funkcji była widoczna w miejscu wywołania. (Należy zwrócić uwagę, że standard nie podejmuje próby określenia charakteru tych optymalizacji).
Widoczność jest zapewniona, jeśli funkcja ma powiązanie wewnętrzne lub jeśli ma powiązanie zewnętrzne, a wywołanie jest w tej samej jednostce tłumaczeniowej co definicja zewnętrzna. W takich przypadkach obecność
inlinesłowa kluczowego w deklaracji lub definicji funkcji nie ma żadnego skutku poza wskazaniem preferencji, że wywołania tej funkcji powinny być optymalizowane w stosunku do wywołań innych funkcji zadeklarowanych bez inlinesłowa kluczowego.
Widoczność jest problemem w przypadku wywołania funkcji z łączem zewnętrznym, gdy wywołanie jest w innej jednostce tłumaczeniowej niż definicja funkcji. W tym przypadku inlinesłowo kluczowe pozwala jednostce tłumaczeniowej zawierającej wywołanie zawierać również lokalną lub wbudowaną definicję funkcji.
Program może zawierać jednostkę tłumaczeniową z definicją zewnętrzną, jednostkę tłumaczeniową z definicją wbudowaną oraz jednostkę tłumaczeniową z deklaracją, ale bez definicji funkcji. Połączenia w drugiej jednostce tłumaczeniowej będą normalnie używać definicji zewnętrznej.
Uznaje się, że wbudowana definicja funkcji jest inną definicją niż definicja zewnętrzna. Jeśli wywołanie jakiejś funkcji funcz łączeniem zewnętrznym występuje, gdy widoczna jest definicja wbudowana, zachowanie jest takie samo, jak w przypadku wywołania innej funkcji, powiedzmy
__func, z połączeniem wewnętrznym. Program zgodny nie może zależeć od wywoływanej funkcji. To jest model inline w standardzie.
Program zgodny nie może polegać na implementacji używającej definicji wbudowanej ani nie może polegać na implementacji korzystającej z definicji zewnętrznej. Adres funkcji jest zawsze adresem odpowiadającym definicji zewnętrznej, ale gdy ten adres jest używany do wywołania funkcji, można użyć definicji wbudowanej. Dlatego poniższy przykład może nie zachowywać 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żywać definicji wbudowanej dla jednego z wywołań saddri używać definicji zewnętrznej dla drugiego, operacja równości nie jest gwarantowana do wartości 1 (prawda). Pokazuje to, że obiekty statyczne zdefiniowane w definicji wbudowanej różnią się od odpowiadających im obiektów w definicji zewnętrznej. To zmotywowało ograniczenie nawet do zdefiniowania constobiektu niebędącego przedmiotem tego typu.
Inlining został dodany do Standardu w taki sposób, że można go zaimplementować z istniejącą technologią konsolidatora, a podzbiór inliningu C99 jest kompatybilny z C ++. Osiągnięto to poprzez wymaganie, aby dokładnie jedna jednostka translacyjna zawierająca definicję funkcji wbudowanej była określona jako ta, która zapewnia zewnętrzną definicję funkcji. Ponieważ ta specyfikacja składa się po prostu z deklaracji, która albo nie zawiera inlinesłowa kluczowego, albo zawiera oba inlinei extern, zostanie również zaakceptowana przez tłumacza C ++.
Inlining w C99 rozszerza specyfikację C ++ na dwa sposoby. Po pierwsze, jeśli funkcja jest zadeklarowana
inlinew jednej jednostce tłumaczeniowej, nie musi być deklarowana inlinew każdej innej jednostce tłumaczeniowej. Pozwala to, na przykład, na funkcję biblioteczną, która ma być wbudowana w bibliotekę, ale dostępna tylko poprzez zewnętrzną definicję w innym miejscu. Alternatywa użycia funkcji opakowującej dla funkcji zewnętrznej wymaga dodatkowej nazwy; może to również negatywnie wpłynąć na wydajność, jeśli tłumacz w rzeczywistości nie wykonuje zastępowania w tekście.
Po drugie, wymóg, aby wszystkie definicje funkcji wbudowanej były „dokładnie takie same”, zostaje zastąpiony wymogiem, że zachowanie programu nie powinno zależeć od tego, czy wywołanie jest implementowane z widoczną definicją wbudowaną, czy też definicją zewnętrzną funkcjonować. Pozwala to na wyspecjalizowanie definicji wbudowanej w celu jej wykorzystania w określonej jednostce tłumaczeniowej. Na przykład zewnętrzna definicja funkcji bibliotecznej może zawierać sprawdzanie poprawności argumentów, które nie jest potrzebne w przypadku wywołań wykonywanych z innych funkcji w tej samej bibliotece. Te rozszerzenia mają pewne zalety; a programiści, którzy są zaniepokojeni kompatybilnością, mogą po prostu przestrzegać bardziej rygorystycznych reguł C ++.
Należy pamiętać, że to jest nie odpowiednie dla implementacje zapewnienie inline definicje standardowych funkcji bibliotecznych w standardowych nagłówków, ponieważ może to złamać trochę starszy kod redeclares standardowe funkcje biblioteczne po tym ich nagłówki. To inlinesłowo kluczowe ma na celu jedynie zapewnienie użytkownikom przenośnego sposobu sugerowania wbudowanych funkcji. Ponieważ standardowe nagłówki nie muszą być przenośne, implementacje mają inne opcje, takie jak:
#define abs(x) __builtin_abs(x)
lub inne nieprzenośne mechanizmy wstawiania standardowych funkcji bibliotecznych.