IMO обе делают функцию иметь только область перевода,
какая разница между "статической" и "статической встроенной" функцией?
UPDATE
почему inline
следует помещать в заголовочный файл, а не .c
файл?
IMO обе делают функцию иметь только область перевода,
какая разница между "статической" и "статической встроенной" функцией?
UPDATE
почему 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 это означает, что функция /variable может использоваться только в пределах одной единицы перевода.
По умолчанию встроенное определение действует только в текущем блоке перевода.
Если класс хранения extern
, идентификатор имеет внешнюю связь, а встроенное определение также предоставляет внешнее определение.
Если класс хранения static
, идентификатор имеет внутреннюю связь, а встроенное определение невидимо в других единицах перевода.
Если класс хранения не указан, встроенное определение отображается только в текущем блоке перевода, но идентификатор по-прежнему имеет внешнюю связь, а внешнее определение должно быть предоставлено в другой единицы перевода. Компилятор может использовать либо встроенное, либо внешнее определение, если функция вызывается в текущем блоке перевода.
Поскольку компилятор свободен для встроенного (и не встроенного) функции, определение которой видимо в текущем блоке перевода (и, благодаря оптимизации времени соединения, даже в разных единицах перевода, хотя стандарт C не на самом деле это объясняет), для большинства практических целей нет разницы между определениями функций static
и static inline
.
Спецификатор inline
(например, класс хранения register
) - это только подсказка компилятора, и компилятор может полностью игнорировать его. Некоммерческие компиляторы, совместимые со стандартами, должны только соблюдать свои побочные эффекты, а оптимизация компиляторов будет выполнять эти оптимизации с явными подсказками или без них.
inline
и register
не являются бесполезными, поскольку они инструктируют компилятор выкидывать ошибки, когда программист пишет код, который сделает невозможным оптимизацию: внешнее определение inline
не может ссылаться на идентификаторы с внутренней связью (поскольку они были бы недоступны в другой единицы перевода) или определить изменяемые локальные переменные со статической продолжительностью хранения (так как они не будут разделять государственные единицы пересчета), и вы не можете принимать адреса register
-qualified variables.
Лично я использую соглашение для обозначения определений функций static
в заголовках также inline
, поскольку основная причина для определения функций в заголовочных файлах - сделать их проницаемыми.
В общем, я использую только функции static inline
и static const
определения объектов в дополнение к объявлениям extern
в заголовках.
Я никогда не писал функцию inline
с классом хранения, отличным от static
.
Из моего опыта работы с GCC я знаю, что static
и static inline
отличается тем, как компилятор предупреждает о неиспользуемых функциях. Точнее, когда вы объявляете функцию static
, и она не используется в текущей блоке перевода, тогда компилятор выдает предупреждение о неиспользуемой функции, но вы можете заблокировать это предупреждение, изменив его на static inline
.
Таким образом, я склонен думать, что static
следует использовать в единицах перевода и использовать дополнительный компилятор проверки для поиска неиспользуемых функций. И static inline
следует использовать в заголовочных файлах для предоставления функций, которые могут быть вставлены (из-за отсутствия внешней связи) без выдачи предупреждений.
К сожалению, я не могу найти никаких доказательств для этой логики. Даже из документации GCC я не смог сделать вывод о том, что inline
запрещает предупреждения о неиспользуемых функциях. Я был бы признателен, если кто-то поделится ссылками с описанием этого.
Одно отличие от уровня языка, но популярного уровня реализации: некоторые версии gcc будут удалять ненужные функции static inline
из вывода по умолчанию, но будут содержать простые функции static
, даже если они не будут отображаться. Я не уверен, какие версии это применимы, но с практической точки зрения это означает, что может быть хорошей идеей всегда использовать inline
для static
функций в заголовках.
В C, static
означает, что функция или переменная, которую вы определяете, могут использоваться только в этом файле (т.е. единица компиляции)
Итак, static inline
означает встроенную функцию, которая может использоваться только в этом файле.
EDIT:
Компилятором должен быть Блок перевода