В чем разница между «статической» и «статической встроенной» функцией? - PullRequest
105 голосов
/ 14 октября 2011

В IMO обе функции имеют область действия только для единицы перевода.

В чем разница между функцией "static" и "static inline"?

Почему inline должно бытьположить в заголовочный файл, а не в .c файл?

Ответы [ 5 ]

91 голосов
/ 14 октября 2011

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

68 голосов
/ 14 октября 2011

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

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

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

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

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

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

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

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

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

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

14 голосов
/ 16 июня 2016

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

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

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

5 голосов
/ 14 октября 2011

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

3 голосов
/ 14 октября 2011

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

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

РЕДАКТИРОВАТЬ:

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

...