6.43 Встроенная функция так же быстра, как макрос
Объявив функцию встроенной, вы можете направить GCC к тому, чтобы вызовы этой функции выполнялись быстрее. Один из способов, которым GCC может этого добиться, — это интегрировать код этой функции в код вызывающих её функций. Это ускоряет выполнение, устраняя накладные расходы на вызов функции; кроме того, если какие-либо фактические значения аргументов являются константами, их известные значения могут позволить упрощения на этапе компиляции, так что не весь код встроенной функции нужно включать. Влияние на размер кода менее предсказуемо; объектный код может быть больше или меньше при встраивании функции, в зависимости от конкретного случая. Вы также можете направить GCC на то, чтобы пытаться интегрировать все достаточно «простые» функции в вызывающие их функции с помощью параметра -finline-functions.
GCC реализует три различные семантики объявления встроенной функции. Одна доступна с -std=gnu89 или -fgnu89-inline или когда gnu_inline атрибут присутствует во всех объявлениях встроенных функций, другая — когда используется -std=c99, -std=gnu99 или параметр для более поздней версии C (без -fgnu89-inline), и третья используется при компиляции C++.
Чтобы объявить функцию встроенной, используйте ключевое слово inline в её объявлении, например так:
static inline int
inc (int *a)
{
return (*a)++;
}
Если вы пишете заголовочный файл для включения в программы ISO C90, напишите __inline__ вместо inline. См. Альтернативные ключевые слова.
Три типа встраивания ведут себя аналогично в двух важных случаях: когда ключевое слово inline используется для функции static, как в приведённом выше примере, и когда функция сначала объявляется без использования ключевого слова inline и затем определяется с inline, как показано ниже:
extern int inc (int *a);
inline int
inc (int *a)
{
return (*a)++;
}
В обоих этих распространённых случаях программа ведёт себя так же, как если бы вы не использовали ключевое слово inline, за исключением её скорости.
Когда функция является и встроенной, и static, если все вызовы функции интегрированы в вызывающую функцию, и адрес функции никогда не используется, то собственный код ассемблера функции никогда не используется. В этом случае GCC фактически не выводит код ассемблера для функции, если вы не укажете параметр -fkeep-inline-functions. Если есть неинтегрированный вызов, то функция компилируется в код ассемблера обычным образом. Функция также должна компилироваться обычным образом, если программа ссылается на её адрес, потому что это нельзя встроить.
Обратите внимание, что некоторые способы использования в определении функции могут сделать её непригодной для замены встроенным кодом. К ним относятся: вариативные функции, использование alloca, использование вычислений goto (см. Метки как значения), использование нелокального goto, использование вложенных функций, использование setjmp, использование __builtin_longjmp и использование __builtin_return или __builtin_apply_args. Использование -Winline предупреждает, когда функция, помеченная inline, не могла быть замещена, и указывает причину неудачи.
Как требуется в ISO C++, GCC рассматривает методы, определённые внутри тела класса, как помеченные как встроенные, даже если они не объявлены явно с помощью ключевого слова inline. Вы можете переопределить это с помощью -fno-default-inline; см. Параметры, контролирующие диалект C++.
GCC не встраивает функции, если не оптимизирует, если вы не укажете атрибут «always_inline» для функции, например так:
/* Prototype. */
inline void foo (const char) __attribute__((always_inline));
Остальная часть этого раздела относится конкретно к встраиванию в GNU C90.
Когда встроенная функция не static, компилятор должен предположить, что могут быть вызовы из других файлов исходного кода; поскольку глобальный символ может быть определён только один раз в любой программе, функция не должна быть определена в других файлах исходного кода, так что вызовы в них не могут быть интегрированы. Поэтому нестатическая встроенная функция всегда компилируется самостоятельно обычным способом.
Если вы укажете как inline, так и extern в определении функции, то определение используется только для встраивания. В любом случае функция не компилируется сама по себе, даже если вы явно ссылаетесь на её адрес. Такой адрес становится внешней ссылкой, как если бы вы только объявили функцию и не определили её.
Это сочетание inline и extern почти так же, как макрос. Способ его использования заключается в размещении определения функции в заголовочном файле с этими ключевыми словами и размещении другой копии определения (без inline и extern) в файле библиотеки. Определение в заголовочном файле приводит к тому, что большинство вызовов функции встраиваются. Если какие-либо использования функции остаются, они ссылаются на единственную копию в библиотеке.
Далее: Переменные, Предыдущее: Выравнивание, Вверх: Расширения языка C [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Inline.html