2010-07-23 15 views
16

In Abschnitt 7.1.1 des Buchs "The C++ Programming Language" der Verfasser:Haben Inline-Funktionen Adressen?

"Inline-Funktion hat immer noch eine eindeutige Adresse und so auch die statischen Variablen einer Inline-Funktion"

Ich bin verwirrt . Wenn ich eine Inline-Funktion habe, kann sie keine Adresse haben. Passiert das auch in C?

+1

Ich denke, dass Satz mehr Kontext benötigt. "Inline-Funktion hat immer noch eine eindeutige Variable" macht keinen Sinn. Warum glauben Sie nicht, dass eine Inline-Funktion eine Adresse haben kann? –

+0

Welche Ausgabe? Ich schaue mir die dritte Ausgabe an und kann nicht sehen, wo das steht. – Clifford

+2

Präzise Zitat aus dem Buch - "Insbesondere eine Inline-Funktion hat immer noch eine eindeutige Adresse und so statische Variablen einer Inline-Funktion". Dies ist die letzte Sache in Abschnitt 7.1.1 - der vorherige Abschnitt beginnt mit "Der Inline-Spezifizierer ist ein * Hinweis * für den Compiler" (meine Hervorhebung). Statische Variablen sind in Abschnitt 7.1.2 behandelt. – Steve314

Antwort

34

Das inline Attribut ist nur ein Hinweis an den Compiler, dass es versuchen sollte, Ihre Funktion zu inline. Es ist immer noch möglich, die Adresse der Funktion zu übernehmen, und in diesem Fall muss der Compiler auch eine Nicht-Inline-Version ausgeben.

Zum Beispiel:

#include <stdio.h> 

inline void f() { 
    printf("hello\n"); 
} 

int main() { 
    f(); 
    void (*g)() = f; 
    g(); 
} 

Der obige Code druckt hello zweimal.

Mein gcc Compiler (mit -O) emittiert Code etwas wie folgt aus:

_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 

Wie Sie sehen können, gibt es zunächst ein Aufruf an puts() und dann ein Aufruf an L__Z1fv() (das ist der verstümmelten Namen f() ist).

+1

+1. Sehr nette Antwort. – ereOn

3

Die Inline-Erweiterung der Funktion hat keine Adresse, aber wenn diese Funktion eine statische Variable hat, hat die Variable eine Adresse. Eine statische Variable ist im Grunde genommen nur eine globale Variable, deren Name nur lokal sichtbar ist (dh innerhalb des Bereichs, in dem sie definiert ist). Andere Variablen in einer Inline-Funktion könnten auf dem Stapel zugewiesen werden (wie wenn sie nicht inline erweitert würden) oder sie könnten nur in Maschinenregistern existieren. Der wichtige Teil ist, dass sie immer noch separate Variablen sind, und genauso handeln müssen, wie die Funktion überhaupt nicht inline erweitert wurde (anders als beispielsweise Makros, bei denen extreme Vorsicht geboten ist, um zu verhindern, dass mehrere Bewertungen Probleme verursachen).

5

Inline-Funktionen haben Adressen, wenn Sie eine benötigen. Standard sagt nur, dass:

Eine Inline-Funktion mit externen Verknüpfung wird in alle Übersetzungseinheiten die gleiche Adresse haben.

+0

Ist das eine Verkörperung oder bezogen auf die * "Als ob" -Regel? – jww

0

Sie können an bestimmten Call-Standorten inlined sein, aber sie existieren immer noch als normale Funktion im Adressraum.

0

Ich glaube, Sie verwechseln die Position des Code-Codes für eingefügte Funktionen mit den Auswirkungen von Inlining. In der Regel visualisieren wir inlined Funktionen als in der aufrufenden Funktion auf der Quellcodeebene platziert. Was das Buch sagt, ist, dass die Variablennamen, einschließlich der Verwendung von Static innerhalb von Inline-Funktionen, genau so behandelt werden, als wäre die Funktion tatsächlich Ihre typische, eigenständige Funktion.

Darüber hinaus garantiert die Behandlung von Funktionen mit dem Inline-Schlüsselwort nicht, dass sie inline sind, und in Fällen, in denen sie nicht möglich sind (z. B. wenn eine Adresse benötigt wird), wird eine nicht inlinierte Version generiert.

5

Es gibt keinen Widerspruch. In Teilen, in denen eine Inline-Funktion aufgerufen wird, kann der Code inline sein. In Bereichen, in denen Sie einen Zeiger zur Funktion verwenden, kann eine Nicht-Inline-Version erstellt werden, um eine Adresse zu haben.