Есть ли у встроенных функций адреса? - PullRequest
16 голосов
/ 23 июля 2010

В разделе 7.1.1 книги "Язык программирования C ++" автор заявляет:

"встроенная функция все еще имеет уникальный адрес, как и статические переменные встроенной функции"

Я в замешательстве.Если у меня есть встроенная функция, то она не может иметь адрес.Это также происходит в C?

Ответы [ 6 ]

35 голосов
/ 23 июля 2010

Атрибут 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

Как видите, сначала вызывается puts(), а затем L__Z1fv() (искаженное имя f()).

6 голосов
/ 23 июля 2010

Встроенные функции имеют адреса, если они вам нужны. Стандарт только говорит, что:

Встроенная функция с внешним связь должна иметь тот же адрес в все переводческие единицы.

5 голосов
/ 23 июля 2010

Нет противоречия. В частях, где вызывается встроенная функция, ее код может быть встроенным. В частях, где вы используете указатель на функцию, может быть создана не встроенная версия, имеющая адрес.

3 голосов
/ 23 июля 2010

Встроенное расширение функции не имеет адреса, но если у этой функции есть статическая переменная, у переменной действительно есть адрес.Статическая переменная - это просто глобальная переменная, чье имя видно только локально (т. Е. В пределах области, в которой она определена).Другие переменные в встроенной функции могут быть размещены в стеке (как если бы они не были развернуты в строке), или они могли бы просто жить в машинных регистрах.Важным моментом является то, что они по-прежнему являются отдельными переменными и должны действовать так, как если бы функция вообще не была развернута встроенной функцией (в отличие, например, от макросов, где требуется крайняя осторожность, чтобы предотвратить возникновение проблем в результате нескольких оценок).1003 *

0 голосов
/ 23 июля 2010

Я думаю, что вы путаете расположение объекта-кода встроенных функций с последствиями встраивания.Обычно мы визуализируем встроенные функции как помещенные в вызывающую функцию на уровне исходного кода.Книга говорит о том, что имена переменных, включая использование static внутри встроенных функций, обрабатываются точно так же, как если бы функция была на самом деле вашей типичной автономной функцией.

Кроме того, обработкафункции с ключевым словом inline, не гарантирует, что они будут встроенными, и для случаев, когда они не могут (например, когда требуется адрес), будет сгенерирована не встроенная версия.

0 голосов
/ 23 июля 2010

Они могут быть встроены на определенных сайтах вызовов, но они все еще существуют как обычная функция в адресном пространстве.

...