IMO оба делают функцию, чтобы иметь только область единицы перевода.
В чем разница между статической и статической встроенной функцией?
Почему следует inline
помещать в файл заголовка, а не в .c
файл?
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
относится к сфере применения. В языке C это означает, что функция / переменная может использоваться только в одной и той же единице перевода.static
(с или безinline
) вполне может быть в заголовке, не вижу причин, почему бы и нет. Шаблоны для C ++, этот вопрос о C.inline
- хороший стиль, имоinline
не инструктирует компилятор делать какие-либо попытки встраивания. Это просто позволяет программисту включать тело функции в несколько единиц трансляции без нарушения ODR. Побочным эффектом этого является то, что это дает возможность для компилятора, когда он будет встраивать функцию, на самом деле это сделать.По умолчанию встроенное определение действительно только в текущей единице перевода.
Если класс хранилища равен
extern
, идентификатор имеет внешнюю связь, а встроенное определение также предоставляет внешнее определение.Если класс хранения равен
static
, идентификатор имеет внутреннюю связь, и встроенное определение невидимо в других единицах перевода.Если класс хранения не указан, встроенное определение видно только в текущей единице трансляции, но идентификатор все еще имеет внешнюю связь, и внешнее определение должно быть предоставлено в другой единице трансляции. Компилятор может использовать либо встроенное, либо внешнее определение, если функция вызывается в текущей единице перевода.
Поскольку компилятор может встраивать (и не встраивать) любую функцию, определение которой отображается в текущей единице перевода (и, благодаря оптимизации времени компоновки, даже в разных единицах перевода, хотя стандарт C на самом деле не учитывает that), для большинства практических целей нет разницы между определениями функций
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
функции и данные, на которые в противном случае не было бы ссылок .