6.7.4 Спецификаторы функций
Новая функция C99: Ключевое слово inline
, адаптированное из C ++, представляет собой спецификатор функции , который
может использоваться только в объявлениях функций. Это полезно для программных оптимизаций, которые требуют
определение функции, которая будет видна на месте вызова. (Обратите внимание, что Стандарт не пытается определить природу этих оптимизаций.)
Видимость гарантируется, если функция имеет внутреннюю связь или если она имеет внешнюю связь и вызов
находится в той же единице перевода, что и внешнее определение. В этих случаях наличие
inline
ключевое слово в объявлении или определении функции не имеет никакого эффекта, кроме указания
предпочтение в том, что вызовы этой функции должны быть оптимизированы по сравнению с вызовами других функций, объявленных без ключевого слова inline
.
Видимость является проблемой для вызова функции с внешней связью, когда вызов находится в
отличается от единицы перевода из определения функции. В этом случае ключевое слово inline
позволяет блоку перевода, содержащему вызов, также содержать локальное или встроенное определение
функция.
Программа может содержать модуль перевода с внешним определением, модуль перевода с
встроенное определение и единица перевода с объявлением, но без определения функции. Вызовы
в последнем переводе блок будет использовать внешнее определение как обычно.
Встроенное определение функции считается отличным от внешнего
определение. Если вызов некоторой функции func
с внешней связью происходит там, где встроенный
определение видно, поведение такое же, как если бы вызов был сделан для другой функции, скажем,
__func
, с внутренней связью. Соответствующая программа не должна зависеть от того, какая функция
называется. Это встроенная модель в стандарте.
Соответствующая программа не должна полагаться на реализацию, использующую встроенное определение, и не может
это зависит от реализации с использованием внешнего определения. Адрес функции всегда является адресом, соответствующим внешнему определению, но когда этот адрес используется для вызова
функция, может быть использовано встроенное определение. Таким образом, следующий пример может не
вести себя как положено.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr(); // unspecified behavior
}
Поскольку реализация может использовать встроенное определение для одного из вызовов saddr
и использовать
внешнее определение для другой, операция равенства не гарантируется для 1
(правда). Это показывает, что статические объекты, определенные во встроенном определении, отличаются от их
соответствующий объект во внешнем определении. Это мотивировало ограничение против даже
определение не const
объекта этого типа.
Вставка была добавлена в стандарт таким образом, чтобы его можно было реализовать с помощью существующего компоновщика.
технология, и подмножество встраивания C99 совместимо с C ++. Это было достигнуто за счет требования, чтобы точно одна единица перевода, содержащая определение встроенной функции, была
определяется как тот, который обеспечивает внешнее определение для функции. Потому что
спецификация состоит просто из объявления, в котором либо отсутствует ключевое слово inline
, либо содержится
inline
и extern
, он также будет принят переводчиком C ++.
Встраивание в C99 расширяет спецификацию C ++ двумя способами. Во-первых, если функция объявленаinline
в одной единице перевода, не нужно объявлять inline
в любой другой единице перевода.Это позволяет, например, использовать библиотечную функцию, которая должна быть встроена в библиотеку, но доступна только через внешнее определение в другом месте.Альтернатива использования функции-оболочки для внешней функции требует дополнительного имени;и это также может отрицательно повлиять на производительность, если переводчик фактически не выполняет встроенную подстановку.
Во-вторых, требование, чтобы все определения встроенной функции были «абсолютно одинаковыми», заменялось требованием, чтобы поведениеПрограмма не должна зависеть от того, реализован ли вызов с видимым встроенным определением или внешним определением функции.Это позволяет встроенному определению быть специализированным для его использования в определенной единице перевода.Например, внешнее определение библиотечной функции может включать проверку некоторого аргумента, которая не требуется для вызовов, выполняемых из других функций в той же библиотеке.Эти расширения предлагают некоторые преимущества;и программисты, которые обеспокоены совместимостью, могут просто соблюдать более строгие правила C ++.
Обратите внимание, что не подходит для реализаций, чтобы обеспечить встроенные определения функций стандартной библиотеки в стандартных заголовках, потому что этоможет сломать некоторый устаревший код, который повторно объявляет стандартные функции библиотеки после включения их заголовков.Ключевое слово inline
предназначено только для того, чтобы предоставить пользователям переносимый способ предложения встроенных функций.Поскольку стандартные заголовки не обязательно должны быть переносимыми, реализации имеют другие параметры, например:
#define abs(x) __builtin_abs(x)
или другие непереносимые механизмы для встраивания функций стандартной библиотеки.