По умолчанию встроенное определение действует только в текущей единице перевода.
Если класс хранения равен extern
, идентификатор имеет внешнюю связь, а встроенное определение также предоставляет внешнее определение.
Если класс хранения static
, идентификатор имеет внутреннюю связь, а встроенное определение невидимо в других единицах перевода.
Если класс хранения не указан, встроенное определение отображается только втекущая единица перевода, но идентификатор все еще имеет внешнюю связь, и внешнее определение должно быть предоставлено в другой единице перевода.Компилятор может свободно использовать либо встроенное, либо внешнее определение, если функция вызывается в текущем модуле перевода.
Поскольку компилятор может встраивать (и не включать) любую функцию, определение которой видно втекущая единица перевода (и, благодаря оптимизации времени соединения, даже в разных единицах перевода, хотя стандарт C на самом деле этого не учитывает), для большинства практических целей нет никакой разницы между static
и static inline
функциейопределения.
Спецификатор inline
(как и класс хранения register
) является только подсказкой компилятора, и компилятор может полностью его игнорировать.Неоптимизирующие компиляторы, соответствующие стандартам, должны учитывать только их побочные эффекты, и оптимизирующие компиляторы будут выполнять эту оптимизацию с явными подсказками или без них.
inline
и register
не бесполезны, поскольку онидайте указание компилятору выдавать ошибки, когда программист пишет код, который сделает невозможной оптимизацию: внешнее определение inline
не может ссылаться на идентификаторы с внутренней связью (так как они были бы недоступны в другом модуле перевода) или определять модифицируемые локальные переменные с помощьюстатическая длительность хранения (поскольку они не разделяют состояние между единицами перевода), и вы не можете использовать адреса register
-квалифицированных переменных.
Лично я использую соглашение для пометки static
определений функцийв заголовках также inline
, так как основная причина помещения определений функций в заголовочные файлы состоит в том, чтобы сделать их встроенными.
В общем, я использую только определения функций static inline
и static const
в дополнение к extern
декларации остроумиязаголовки hin.
Я никогда не писал функцию inline
с классом хранения, отличным от static
.