документация gcc содержит следующее:
Когда функция является как встроенной, так и статической, если все вызовы
Функция интегрирована в вызывающего, и адрес функции
никогда не используется, то собственный код ассемблера функции никогда не будет
ссылки. В этом случае GCC фактически не выводит код ассемблера
для функции, если вы не укажете опцию
-fkeep-рядные функции. Некоторые вызовы не могут быть интегрированы по разным причинам (в частности, вызовы, предшествующие определению функции
не может быть интегрирован, и ни один не может рекурсивные вызовы в пределах
определение).
Это всегда звучало абсурдно для меня — почему современный компилятор такой глупый? После быстрого теста это кажется неверным.
Тестовый код:
static inline int foo();
int bar() {
return foo();
}
int foo() {
return 42;
}
Результат с gcc-4.9.2 в Linux содержит код для bar()
но не для foo()
, Ты это видишь foo()
был интегрирован:
bar:
.LFB0:
.cfi_startproc
movl $42, %eax
ret
.cfi_endproc
Если я компилирую как C ++, результат будет таким же, за исключением искажения имени.
Вопреки документации, несмотря на foo()
определяется после звонка в bar()
, foo()
был полностью интегрирован в bar()
,
Я неправильно понимаю документацию или это неправильно? Возможно, это правильно для более сложного случая?
Я не знаю, есть ли техническое различие между «интегрировать» и «встроенный», но я подозреваю, что «интегрировать» используется, чтобы отличить от ключевого слова inline
и это просто относится к встраиванию функции (отсюда и название).
Этот вопрос помечен как C и C ++, потому что эта часть документации gcc относится к «семейству языков C», и я ожидаю, что ответ будет одинаковым для двух языков.
Gcc использовал для компиляции и оптимизации по одной функции за раз, как только они были проанализированы, перед анализом следующей. IIRC, только в срок 4.X они представили -funit-at-a-time
опция, которая откладывала оптимизацию после прочтения всего модуля компиляции, а затем они ждали некоторых выпусков, чтобы включить его по умолчанию.
Возможность встраивания функции, определенной после вызова, вероятно, была введена как часть -funit-at-a-time
работа, и документация inline (упоминание о вызовах, предшествующих определению датируется, по крайней мере, до 2.95) тогда не обновлялось.