2012-01-16 10 views
10

Mam static inline funkcję zdefiniowaną w pliku H inline, aw pewnym momencie w pliku C, mam przypisując wskaźnik do funkcji, coś takiego:C: Wskaźnik do funkcji

Foo.h :

static inline void frobnicate(void) { 
    // frobs something. 
} 

foo.c

#include "foo.h" 

void execute(void (*func)(void)) { 
    func(); 
} 

void blahBlahBlah(void) { 
    execute(frobnicate); 
} 

bar.c

#include "foo.h" 
// ... 
frobnicate(); 

Więc myślę, że to, co się tutaj stanie, to, że kompilator zainicjuje połączenie z frobnicate z paska.c, ale w foo.c będzie musiał utworzyć funkcję do implementacji frobnicate, aby mógł działać wskaźnik do niego.

Czy każdy może potwierdzić, że moje zrozumienie jest prawidłowe, i poprawić mnie w inny sposób?

+2

* Możesz * potwierdzić, czytając wygenerowany kod. Nie sądzę, że istnieje określony sposób, w jaki to * działa *. Nie zdziwiłbym się, gdyby kompilator napisał: "ktoś chce adresu, więc nie wpisujmy go". – unwind

+7

Należy pamiętać, że 'inline' to tylko _suggestion_ do kompilatora –

Odpowiedz

10

inline jest jednym z mylących nazw standardu C. Jego głównym znaczeniem jest możliwość umieszczenia definicji funkcji w pliku nagłówkowym bez konieczności radzenia sobie z problemami "wielokrotnej definicji" w czasie łączenia.

Oficjalny sposób w C99 i C11, aby zrobić to, co chcesz osiągnąć, to mieć definicję inline w pliku nagłówkowym, bez static. Ponieważ potrzebujesz również emitowanego symbolu, powinieneś powiedzieć kompilatorowi, w której jednostce kompilacji powinno to być. Taką instancję można wykonać, mając w tym pliku .c deklarację, w której pominięto słowo kluczowe inline.

W naturalny sposób można użyć pliku .c, w którym faktycznie potrzebny jest symbol.

+0

Jeśli definicja wstawiania znajduje się w pliku nagłówkowym bez 'static', to czy nie miałbym wielu definicji o tej samej nazwie (funkcja inline) podczas próby połączenia? – brianmearns

+0

Będziesz mieć problemy z połączeniem. Albo uczyń go 'statycznym inline' i zaryzykuj wiele definicji, albo zrezygnuj z linii.Możesz także utworzyć wrapper, który będzie w pliku C i nie będzie wstawiany, i weź na niego wskaźnik (brak trafienia wydajnościowego, ponieważ prawdziwa funkcja zostanie wstawiona do opakowania). – ugoren

+0

@bmearns, z kompilatorem zgodnym z C99 nie będziesz mieć problemu z połączeniem. Dokładnie taki jest sens słowa kluczowego 'inline'. http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ –

7

Tak, masz rację. Po przejściu do funkcji kompilator musi utworzyć wersję "stand alone", w której kod można nazwać normalną funkcją.

Zaletą wbudowywania funkcji jest to, że kod wywoławczy nie musi być tworzony i można zastosować dowolną inną optymalizację w celu zintegrowania zarówno funkcji wywołującej, jak i funkcji wstawionej. Ale kiedy musisz wykonać zwykłe wywołanie funkcji (jak wtedy, gdy podasz adres, aby wywołać to później), te optymalizacje nie są już możliwe.

+2

Może to być prawdą dla wielu kompilatorów, ale nie mogę sobie wyobrazić, dlaczego kompilator musiałby to zrobić. Przykład OP można było dość łatwo przedstawić nawet w przypadku wskaźnika funkcji. –

+0

'inline' to zalecenie. Jeśli kompilator nie może wstawić, nie będzie, a jeśli nie, może nadal nie zdecydować (i może wstawiać nawet bez słowa kluczowego 'inline'). Wskaźniki funkcyjne zazwyczaj uniemożliwiają wstawianie, chociaż w tym przypadku kompilator może stwierdzić, że nie (lub może nie przeszkadza). – ugoren

+0

Tak, w takim przypadku można wstawić funkcję. Zakładałem, że jest to uproszczona wersja problemu. Ale masz rację. – Governa