Spec-Zone.ru › GCC 4

6.39 Встроенная функция так же быстра, как макрос

Объявив функцию встроенной, вы можете направить GCC на ускорение вызовов этой функции. Один из способов, которым GCC может этого добиться, — это интегрировать код этой функции в код её вызывающих функций. Это ускоряет выполнение, устраняя накладные расходы вызова функции; кроме того, если какие-либо фактические значения аргументов являются константами, их известные значения могут позволить упрощения во время компиляции, так что не весь код встроенной функции необходимо включать. Влияние на размер кода предсказуемо меньше; объектный код может быть больше или меньше при встроенном вызове функции, в зависимости от конкретного случая. Вы также можете направить GCC на попытку интегрировать все достаточно простые функции в свои вызывающие функции с помощью опции -finline-functions.

GCC реализует три различные семантики объявления встроенной функции. Одна доступна с помощью -std=gnu89 или -fgnu89-inline или когда атрибут gnu_inline присутствует во всех объявлениях встроенных функций, другая, когда -std=c99, -std=c11, -std=gnu99 или -std=gnu11 (без -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, использование типов данных переменной длины (см. Переменная длина), использование вычисленных переходов (см. Метки как значения), использование нелокальных переходов и вложенных функций (см. Вложенные функции). Использование -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, компилятор должен предположить, что могут быть вызовы из других файлов; поскольку глобальный символ может быть определён только один раз в любой программе, функция не должна быть определена в других исходных файлах, поэтому вызовы в них не могут быть интегрированы. Поэтому не-static встроенная функция всегда компилируется самостоятельно обычным способом.

Если вы укажете и inline, и extern в определении функции, то определение используется только для встроенных вызовов. Ни в коем случае функция не компилируется самостоятельно, даже если вы явно ссылаетесь на её адрес. Такой адрес становится внешней ссылкой, как если бы вы только объявили функцию и не определили её.

Это сочетание inline и extern практически равнозначно макросу. Способ использования — поместить определение функции в заголовочный файл с этими ключевыми словами и поместить другую копию определения (без inline и extern) в файл библиотеки. Определение в заголовочном файле заставляет большинство вызовов функции быть встроенными. Если какие-либо применения функции остаются, они ссылаются на единственную копию в библиотеке.

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Inline.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API