В разделе 7.1.1 из книги "Язык Программирования на C++" состояния автора:
"подставляемая функция все еще имеет уникальный адрес и также - статические переменные подставляемой функции"
Я смущен. Если у меня есть подставляемая функция затем, она не может иметь адреса. Это происходит в C также?
Атрибут inline
- это просто подсказка компилятору, что он должен попытаться встроить вашу функцию. По-прежнему можно получить адрес функции, и в этом случае компилятор также должен будет выдать не встроенную версию.
Например:
#include <stdio.h>
inline void f() {
printf("hello\n");
}
int main() {
f();
void (*g)() = f;
g();
}
Приведенный выше код печатает hello
дважды.
Мой компилятор gcc
(с -O
) выдает примерно такой код:
_main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
call ___i686.get_pc_thunk.bx
"L00000000002$pb":
leal LC0-"L00000000002$pb"(%ebx), %eax
movl %eax, (%esp)
call L_puts$stub ; inlined call to f()
call L__Z1fv$stub ; function pointer call to f() (g is optimised away)
movl $0, %eax
addl $20, %esp
popl %ebx
popl %ebp
ret
Как видите, сначала выполняется вызов put ()
, а затем вызов L__Z1fv ()
(искаженное имя f ()
).
Они могут быть встроены в определенные сайты вызовов, но они все еще существуют как нормальная функция в адресном пространстве.
Я думаю, вы путаете расположение объектного кода встроенных функций с последствиями встраивания. Обычно мы визуализируем встроенные функции как размещенные внутри вызывающей функции на уровне исходного кода. В книге говорится, что имена переменных, включая использование static во встроенных функциях, обрабатываются так же, как если бы функция была вашей типичной автономной функцией.
Кроме того, обработка функций с помощью ключевого слова inline не гарантирует, что они будут встроены, а в случаях, когда это невозможно (например, при запросе адреса), будет сгенерирована не встроенная версия.
У встроенных функций есть адреса, если они вам нужны. Стандарт только говорит, что:
Встроенная функция с внешним связь должна иметь тот же адрес в все единицы перевода.
Нет противоречия. В тех частях, где вызывается встроенная функция, ее код может быть встроен. В тех частях, где вы используете указатель на функцию, может быть создана не встроенная версия с адресом.
Встроенное расширение функции не имеет адреса, но если эта функция имеет статическую переменную, у переменной есть адрес. Статическая переменная - это, по сути, просто глобальная переменная, имя которой отображается только локально (то есть в пределах области, в которой она определена). Другие переменные во встроенной функции могут быть размещены в стеке (как если бы они не были развернуты встроенными) или они могли просто жить в машинных регистрах. Важная часть состоит в том, что они по-прежнему являются отдельными переменными и должны действовать так же, как функция вообще не была расширена встроенной (в отличие, например, от макросов, где требуется особая осторожность, чтобы множественные вычисления не вызывали проблем).