6.45 Встроенная функция так же быстра, как макрос
Объявив функцию встроенной, вы можете направить 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-12.2.0/gcc/Inline.html