Відповіді:
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 це означає, що функцію / змінну можна використовувати лише в межах одного блоку перекладу.