Odpowiedzi:
inline
instruuje kompilator, aby spróbował osadzić zawartość funkcji w kodzie wywołującym zamiast wykonywania rzeczywistego wywołania.
W przypadku małych funkcji, które są często wywoływane, mogą mieć duży wpływ na wydajność.
Jest to jednak tylko „wskazówka” i kompilator może ją zignorować, a większość kompilatorów będzie próbować wstawiać ją w tekście, nawet jeśli słowo kluczowe nie jest używane, w ramach optymalizacji, o ile jest to możliwe.
na przykład:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
Ta ścisła pętla wykona wywołanie funkcji w każdej iteracji, a zawartość funkcji jest w rzeczywistości znacznie mniejsza niż kod, który kompilator musi umieścić, aby wykonać wywołanie. inline
zasadniczo poinstruuje kompilator, aby przekonwertował powyższy kod na odpowiednik:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Pomijanie rzeczywistego wywołania funkcji i powrotu
Oczywiście jest to przykład, który ma pokazać, a nie prawdziwy fragment kodu.
static
odnosi się do zakresu. W C oznacza to, że funkcja / zmienna może być używana tylko w tej samej jednostce tłumaczeniowej.
static
(z lub bez inline
) może być w nagłówku doskonale, nie widzę powodu, dlaczego nie. Szablony są dla C ++, to pytanie dotyczy C.
inline
jest dobrym stylem, imo
inline
nie instruuje kompilatora, aby podejmował jakiekolwiek próby wstawiania. Pozwala tylko programiście na włączenie treści funkcji do wielu jednostek tłumaczeniowych bez naruszenia ODR. Efektem ubocznym tego jest to, że umożliwia kompilatorowi, gdy mógłby to zrobić, w rzeczywistości.
Domyślnie definicja wbudowana obowiązuje tylko w bieżącej jednostce tłumaczeniowej.
Jeśli klasa pamięci to extern
, identyfikator ma połączenie zewnętrzne, a definicja wbudowana zawiera również definicję zewnętrzną.
Jeśli klasa pamięci to static
, identyfikator jest powiązany wewnętrznie, a definicja wbudowana jest niewidoczna w innych jednostkach tłumaczeniowych.
Jeśli klasa pamięci nie jest określona, definicja wbudowana jest widoczna tylko w bieżącej jednostce tłumaczeniowej, ale identyfikator nadal jest powiązany z zewnętrzną linią i należy podać definicję zewnętrzną w innej jednostce tłumaczeniowej. Kompilator może swobodnie używać definicji wbudowanej lub zewnętrznej, jeśli funkcja jest wywoływana w ramach bieżącej jednostki tłumaczenia.
Ponieważ kompilator może wbudować (a nie wbudować) dowolną funkcję, której definicja jest widoczna w bieżącej jednostce tłumaczeniowej (a dzięki optymalizacji czasu łącza, nawet w różnych jednostkach tłumaczeniowych, chociaż standard C tak naprawdę nie uwzględnia that), z większości praktycznych powodów nie ma różnicy między definicjami funkcji static
a static inline
.
Specyfikator inline
(podobnie jak register
klasa pamięci masowej) jest tylko wskazówką kompilatora, a kompilator może go całkowicie zignorować. Zgodne ze standardami nieoptymalizujące kompilatory muszą tylko uwzględniać ich skutki uboczne, a optymalizujące kompilatory będą przeprowadzać te optymalizacje z lub bez wyraźnych wskazówek.
inline
i register
nie są jednak bezużyteczne, ponieważ instruują kompilator, aby zgłaszał błędy, gdy programista pisze kod, który uniemożliwiłby optymalizacje: inline
definicja zewnętrzna nie może odwoływać się do identyfikatorów z powiązaniem wewnętrznym (ponieważ byłyby one niedostępne w innej jednostce tłumaczenia) lub zdefiniuj modyfikowalne zmienne lokalne ze statycznym czasem przechowywania (ponieważ nie będą one dzielić stanu w jednostkach tłumaczeniowych) i nie możesz wziąć adresówregister
zmiennych kwalifikowanych.
Osobiście używam konwencji do oznaczania static
definicji funkcji również w nagłówkach inline
, ponieważ głównym powodem umieszczania definicji funkcji w plikach nagłówkowych jest uczynienie ich inlinowalnymi.
Ogólnie rzecz biorąc, oprócz definicji używam tylko definicji static inline
funkcji i static const
obiektówextern
deklaracji w nagłówkach .
Nigdy nie napisałem inline
funkcji z inną klasą pamięci niż static
.
inline
, że faktycznie dotyczyła wstawiania, jest myląca i prawdopodobnie niepoprawna. Żaden współczesny kompilator nie używa go jako wskazówki do wstawiania lub wymagania tego w celu włączenia funkcji wstawiania w tekście.
static
i static inline
. Oba powodują, że definicja jest niewidoczna dla innych jednostek tłumaczeniowych. Więc jaki byłby rozsądny powód, żeby static inline
zamiast pisać static
?
Z mojego doświadczenia z GCC wiem to static
i static inline
różni się sposobem, w jaki kompilator wyświetla ostrzeżenia o nieużywanych funkcjach. Dokładniej, gdy zadeklarujesz static
funkcję i nie jest ona używana w bieżącej jednostce tłumaczącej, kompilator wyświetli ostrzeżenie o nieużywanej funkcji, ale możesz zablokować to ostrzeżenie, zmieniając je nastatic inline
.
Dlatego uważam, że static
powinien być używany w jednostkach tłumaczeniowych i korzystać z dodatkowego kompilatora sprawdzającego, aby znaleźć nieużywane funkcje. I static inline
powinien być używany w plikach nagłówkowych, aby udostępniać funkcje, które można wstawić (z powodu braku zewnętrznych połączeń) bez wyświetlania ostrzeżeń.
Niestety nie mogę znaleźć żadnych dowodów na tę logikę. Nawet z dokumentacji GCC nie byłem w stanie wywnioskować, że inline
blokuje ostrzeżenia o nieużywanych funkcjach. Byłbym wdzięczny, gdyby ktoś udostępnił linki do opisu tego.
warning: unused function 'function' [clang-diagnostic-unused-function]
do static inline
funkcji podczas budowania zclang-tidy
(v8.0.1), który jest używany w innej jednostce tłumaczeniowej. Ale zdecydowanie jest to jedno z najlepszych wyjaśnień i powodów do łączenia static
& inline
!
W C, static
oznacza że zdefiniowana funkcja lub zmienna może być używana tylko w tym pliku (tj. Jednostce kompilacji)
Tak, static inline
oznacza funkcję inline, który może być używany tylko w tym pliku.
EDYTOWAĆ:
Jednostką kompilacyjną powinna być Jednostka tłumacząca
the compile unit
jest coś, co napisałem przez pomyłkę, nie ma czegoś takiego, rzeczywista terminologia totranslation unit
Jedna różnica, która nie dotyczy poziomu języka, ale popularnego poziomu implementacji: niektóre wersje gcc static inline
domyślnie usuwają funkcje, do których nie ma odniesień, z wyjścia, ale zachowują zwykłe static
funkcje, nawet jeśli nie mają odniesień. Nie jestem pewien, które wersje to dotyczy, ale z praktycznego punktu widzenia oznacza to, że może to być dobry pomysł, aby zawsze korzystać inline
z static
funkcji w nagłówkach.
inline
w definicji? Czy sugerujesz również, że nie używasz go do extern
funkcji?
attribute((used))
i jego użycie, aby umożliwić asm odwoływanie się do static
funkcji i danych bez odniesień .
static
dotyczy zakresu. W C oznacza to, że funkcja / zmienna może być używana tylko w tej samej jednostce tłumaczeniowej.