Spec-Zone.ru › GCC 11

Далее: Когда обращаются к объекту volatile?, Предыдущее: Определение выравнивания функций, типов или переменных, Вверх: Расширения семейства языков C [Оглавление][Индекс]

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) в файл библиотеки. Определение в заголовочном файле приводит к тому, что большинство вызовов функции встраиваются. Если какие-либо использования функции остаются, они ссылаются на единственную копию в библиотеке.

Далее: Когда обращаются к volatile объекту?, Предыдущее: Определение выравнивания функций, типов или переменных, Вверх: Расширения семейства языков C [Оглавление][Индекс]

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

Spec-Zone.ru

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