Відповіді:
inline
доручає компілятору спробувати вставити вміст функції в код виклику, а не виконувати фактичний виклик.
Для невеликих функцій, які часто викликаються, які можуть значно змінити продуктивність.
Однак це лише "натяк", і компілятор може ігнорувати це, і більшість компіляторів намагаються "вбудувати" навіть тоді, коли ключове слово не використовується, як частина оптимізацій, де це можливо.
наприклад:
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*/};
Цей щільний цикл виконуватиме виклик функції під час кожної ітерації, а вміст функції насправді значно менший, ніж код, який потрібно ввести компілятору для виконання виклику. inline
по суті, доручить компілятору перетворити код вище в еквівалент:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Пропуск фактичного виклику функції та повернення
Очевидно, що це приклад, щоб показати суть, а не справжній фрагмент коду.
static
стосується сфери застосування. У C це означає, що функцію / змінну можна використовувати лише в межах одного блоку перекладу.
static
(з або без inline
) може бути в шапці ідеально добре, не бачте причини, чому б ні. Шаблони призначені для C ++, це питання стосується C.
inline
є хорошим стилем, imo
inline
не вказує компілятору робити будь-які спроби вбудовування. Він просто дозволяє програмісту включити функціональне тіло в декілька блоків перекладу без порушення ODR. Побічним ефектом цього є те, що це дає можливість для компілятора, коли він буде вбудовувати функцію, насправді це зробити.
За замовчуванням визначення вбудованого тексту є дійсним лише в поточній одиниці перекладу.
Якщо клас зберігання є extern
, ідентифікатор має зовнішню зв'язок, а вбудоване визначення також забезпечує зовнішнє визначення.
Якщо клас зберігання є static
, ідентифікатор має внутрішню зв'язок, а вбудоване визначення невидиме в інших одиницях перекладу.
Якщо клас зберігання не визначено, визначення вбудованого тексту видно лише в поточному блоці перекладу, але ідентифікатор все ще має зовнішню зв'язок і зовнішнє визначення повинно бути надано в іншому блоці перекладу. Компілятор вільний використовувати або вбудоване, або зовнішнє визначення, якщо функція викликається в поточному блоці перекладу.
Оскільки компілятор вільний вбудовувати (а не вбудовувати) будь-яку функцію, визначення якої видно в поточному блоці перекладу (і, завдяки оптимізації часу зв’язку, навіть у різних одиницях перекладу, хоча стандарт C насправді не враховує що) для більшості практичних цілей немає різниці між визначеннями static
та static inline
функціями.
Специфікатор inline
(як register
клас зберігання) - лише підказка компілятора, і компілятор вільний повністю ігнорувати його. Неоптимізуючі компілятори, що відповідають стандартам, повинні лише виконувати їх побічні ефекти, і оптимізація компіляторів виконує ці оптимізації з явними підказками або без них.
inline
і register
вони не марні, оскільки вони доручають компілятору викидати помилки, коли програміст записує код, який би унеможливив оптимізацію. Зовнішнє inline
визначення не може посилатися на ідентифікатори з внутрішнім зв’язком (оскільки вони були б недоступні в іншому блоці перекладу) або визначити місцеві змінні, що можуть змінюватися, зі статичною тривалістю зберігання (оскільки вони не поділять стан на одиниці перекладу), і ви не можете приймати адреси register
-класифікованих змінних.
Особисто я використовую конвенцію для позначення static
визначень функцій у заголовках inline
, оскільки головна причина розміщення визначень функцій у файлах заголовків полягає у тому, щоб зробити їх неприступними.
Взагалі, я використовую лише визначення static inline
функцій та static const
об'єктів на додаток до extern
декларацій у заголовках.
Я ніколи не писав inline
функції з класом зберігання, відмінним від static
.
inline
, ніби вона насправді застосовується до вкладок, є оманливою і, мабуть, невірною. Жоден сучасний компілятор не використовує його як підказку для вбудованого чи потрібного для того, щоб увімкнути вбудовану функцію.
static
і static inline
. Вони обидва роблять це визначення невидимим для інших перекладацьких одиниць. Отже, що було б розумним приводом писати static inline
замість static
?
З мого досвіду роботи з GCC я знаю це static
і static inline
відрізняється тим, як компілятор видає попередження про невикористані функції. Точніше, коли ви оголошуєте static
функцію, і вона не використовується в поточному блоці перекладу, тоді компілятор видає попередження про невикористану функцію, але ви можете заборонити це попередження, змінивши його на static inline
.
Тому я схильний вважати, що static
слід використовувати в одиницях перекладу і користуватися додатковим компілятором перевірки, щоб знайти невикористані функції. І їх static inline
слід використовувати у файлах заголовків для надання функцій, які можуть бути вбудовані (через відсутність зовнішньої зв'язку) без видачі попереджень.
На жаль, я не можу знайти жодних доказів такої логіки. Навіть із документації GCC я не зміг зробити висновок, що inline
гальмує попередження про невикористані функції. Буду вдячний, якщо хтось поділиться посиланнями на його опис.
warning: unused function 'function' [clang-diagnostic-unused-function]
для static inline
функції при складанні clang-tidy
(v8.0.1), який використовується в іншій одиниці трансляції. Але, безумовно, це одне з найкращих пояснень та причин поєднання static
& inline
!
У C static
означає, що функція або змінна, яку ви визначаєте, може використовуватися лише в цьому файлі (тобто блоці компіляції)
Отже, static inline
означає вбудовану функцію, яку можна використовувати лише в цьому файлі.
Редагувати:
Одиницею компіляції має бути Блок перекладу
the compile unit
, що я написав помилково, такого немає, власне термінологіяtranslation unit
Одна відмінність, що не на мовному рівні, а на популярному рівні реалізації: певні версії gcc видалять невибрані static inline
функції з виводу за замовчуванням, але зберігатимуть звичайні static
функції, навіть якщо їх не визначають. Я не впевнений , які версії це відноситься, але з практичної точки зору це означає , що вона може бути гарною ідеєю , щоб завжди використовувати inline
для static
функцій в заголовках.
inline
визначення? Ви також маєте на увазі не використовувати його для extern
функцій?
attribute((used))
та її використання, щоб дозволити asm посилатися на інакше невіднесені static
функції та дані.
static
стосується сфери застосування. У C це означає, що функцію / змінну можна використовувати лише в межах одного блоку перекладу.