Какая разница между "статической" и "статической встроенной" функцией?

IMO обе делают функцию иметь только область перевода,

какая разница между "статической" и "статической встроенной" функцией?

UPDATE

почему inline следует помещать в заголовочный файл, а не .c файл?

Ответ 1

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 может использоваться только в пределах одной единицы перевода.

Ответ 2

По умолчанию встроенное определение действует только в текущем блоке перевода.

Если класс хранения extern, идентификатор имеет внешнюю связь, а встроенное определение также предоставляет внешнее определение.

Если класс хранения static, идентификатор имеет внутреннюю связь, а встроенное определение невидимо в других единицах перевода.

Если класс хранения не указан, встроенное определение отображается только в текущем блоке перевода, но идентификатор по-прежнему имеет внешнюю связь, а внешнее определение должно быть предоставлено в другой единицы перевода. Компилятор может использовать либо встроенное, либо внешнее определение, если функция вызывается в текущем блоке перевода.

Поскольку компилятор свободен для встроенного (и не встроенного) функции, определение которой видимо в текущем блоке перевода (и, благодаря оптимизации времени соединения, даже в разных единицах перевода, хотя стандарт C не на самом деле это объясняет), для большинства практических целей нет разницы между определениями функций static и static inline.

Спецификатор inline (например, класс хранения register) - это только подсказка компилятора, и компилятор может полностью игнорировать его. Некоммерческие компиляторы, совместимые со стандартами, должны только соблюдать свои побочные эффекты, а оптимизация компиляторов будет выполнять эти оптимизации с явными подсказками или без них.

inline и register не являются бесполезными, поскольку они инструктируют компилятор выкидывать ошибки, когда программист пишет код, который сделает невозможным оптимизацию: внешнее определение inline не может ссылаться на идентификаторы с внутренней связью (поскольку они были бы недоступны в другой единицы перевода) или определить изменяемые локальные переменные со статической продолжительностью хранения (так как они не будут разделять государственные единицы пересчета), и вы не можете принимать адреса register -qualified variables.

Лично я использую соглашение для обозначения определений функций static в заголовках также inline, поскольку основная причина для определения функций в заголовочных файлах - сделать их проницаемыми.

В общем, я использую только функции static inline и static const определения объектов в дополнение к объявлениям extern в заголовках.

Я никогда не писал функцию inline с классом хранения, отличным от static.

Ответ 3

Из моего опыта работы с GCC я знаю, что static и static inline отличается тем, как компилятор предупреждает о неиспользуемых функциях. Точнее, когда вы объявляете функцию static, и она не используется в текущей блоке перевода, тогда компилятор выдает предупреждение о неиспользуемой функции, но вы можете заблокировать это предупреждение, изменив его на static inline.

Таким образом, я склонен думать, что static следует использовать в единицах перевода и использовать дополнительный компилятор проверки для поиска неиспользуемых функций. И static inline следует использовать в заголовочных файлах для предоставления функций, которые могут быть вставлены (из-за отсутствия внешней связи) без выдачи предупреждений.

К сожалению, я не могу найти никаких доказательств для этой логики. Даже из документации GCC я не смог сделать вывод о том, что inline запрещает предупреждения о неиспользуемых функциях. Я был бы признателен, если кто-то поделится ссылками с описанием этого.

Ответ 4

Одно отличие от уровня языка, но популярного уровня реализации: некоторые версии gcc будут удалять ненужные функции static inline из вывода по умолчанию, но будут содержать простые функции static, даже если они не будут отображаться. Я не уверен, какие версии это применимы, но с практической точки зрения это означает, что может быть хорошей идеей всегда использовать inline для static функций в заголовках.

Ответ 5

В C, static означает, что функция или переменная, которую вы определяете, могут использоваться только в этом файле (т.е. единица компиляции)

Итак, static inline означает встроенную функцию, которая может использоваться только в этом файле.

EDIT:

Компилятором должен быть Блок перевода