IMO obie sprawiają, że funkcja obejmuje tylko zakres jednostki tłumaczeniowej.
Jaka jest różnica między funkcją „static” a „static inline”?
Dlaczego należy inline
umieścić w pliku nagłówkowym, a nie w .c
pliku?
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
dotyczy zakresu. W C oznacza to, że funkcja / zmienna może być używana tylko w tej samej jednostce tłumaczeniowej.static
(z lub bezinline
) może być w nagłówku doskonale, nie widzę powodu, dlaczego nie. Szablony są dla C ++, to pytanie dotyczy C.inline
jest dobrym stylem, imoinline
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
astatic inline
.Specyfikator
inline
(podobnie jakregister
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
iregister
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łówkachinline
, 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 istatic const
obiektówextern
deklaracji w nagłówkach .Nigdy nie napisałem
inline
funkcji z inną klasą pamięci niżstatic
.źródło
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
istatic inline
. Oba powodują, że definicja jest niewidoczna dla innych jednostek tłumaczeniowych. Więc jaki byłby rozsądny powód, żebystatic inline
zamiast pisaćstatic
?Z mojego doświadczenia z GCC wiem to
static
istatic inline
różni się sposobem, w jaki kompilator wyświetla ostrzeżenia o nieużywanych funkcjach. Dokładniej, gdy zadeklarujeszstatic
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. Istatic 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.źródło
warning: unused function 'function' [clang-diagnostic-unused-function]
dostatic 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 łączeniastatic
&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
źródło
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łestatic
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
zstatic
funkcji w nagłówkach.źródło
inline
w definicji? Czy sugerujesz również, że nie używasz go doextern
funkcji?attribute((used))
i jego użycie, aby umożliwić asm odwoływanie się dostatic
funkcji i danych bez odniesień .