Was ist der Unterschied in der Praxis zwischen Inline und #define?

8

Wie der Titel sagt; Was ist der Unterschied in der Praxis zwischen dem Inline-Schlüsselwort und der Präprozessor-Direktive #define?

    
eliego 24.08.2010, 08:03
quelle

6 Antworten

37

#define ist ein Präprozessor-Werkzeug und hat Makrosemantik. Beachten Sie dies, wenn max(a,b) ein Makro ist, das als

definiert ist

#define max(a,b) ((a)>(b)?(a):(b)) :

Beispiel 1:

val = max(100, GetBloodSample(BS_LDL)) würde zusätzliches unschuldiges Blut verschütten, weil die Funktion tatsächlich zweimal aufgerufen wird. Dies kann zu erheblichen Leistungsunterschieden bei realen Anwendungen führen.

Beispiel 2:

val = max(3, schroedingerCat.GetNumPaws()) Dies zeigt einen schwerwiegenden Unterschied in der Programmlogik , da dieser unerwartet eine Zahl zurückgeben kann, die kleiner als 3 ist - etwas, das der Benutzer nicht erwartet.

Beispiel 3:

val = max(x, y++) könnte y mehr als einmal inkrementieren.

Mit Inline-Funktionen wird keiner von diesen passieren.

Der Hauptgrund ist, dass das Makrokonzept die Transparenz der Implementierung (textueller Codeaustausch) und Inline auf die richtigen Sprachkonzepte abzielt, wodurch die Aufrufsemantik für den Benutzer transparenter wird.

    
Pavel Radzivilovsky 24.08.2010, 08:06
quelle
2

Funktionen (ob inline oder nicht) und Makros erfüllen unterschiedliche Zwecke. Ihr Unterschied sollte nicht als ideologisch betrachtet werden, wie manche es zu nehmen scheinen, und was noch wichtiger ist, sie können gut zusammenarbeiten.

Makros sind Textersetzungen, die zum Zeitpunkt der Kompilierung durchgeführt werden, und sie können Dinge wie

tun %Vor%

gibt Ihnen einen Kompilierzeitausdruck darüber, ob ein ganzzahliger Typ signiert ist oder nicht. Das heißt, sie werden idealerweise verwendet, wenn der Typ eines Ausdrucks nicht bekannt ist (bei der Definition) und Sie etwas dagegen tun möchten. Auf der anderen Seite besteht die Gefahr bei Makros darin, dass ihre Argumente mehrmals ausgewertet werden können, was aufgrund von Nebenwirkungen schlecht ist.

Funktionen ( inline ) auf der anderen Seite sind getippt, was sie strenger oder negativer formuliert weniger flexibel macht. Betrachten Sie die Funktionen

%Vor%

Der erste implementiert die triviale Funktion abs für einen vorzeichenlosen ganzzahligen Typ. Die zweite implementiert es für einen signierten Typ. (Ja, es braucht ein nicht unterzeichnet als Argument, das ist für den Zweck.)

Wir können diese mit jedem ganzzahligen Typ verwenden. Aber der Rückgabetyp wird immer die größte Breite haben und es gibt eine gewisse Schwierigkeit zu wissen, wie man zwischen den beiden wählen kann.

Jetzt mit dem folgenden Makro

%Vor%

Wir haben ein

implementiert
  • Familie von Funktionen
  • das funktioniert für jeden integralen Typ
  • das sein Argument nur einmal bewertet
  • für welche kürzlichen und anständigen Der Compiler erstellt den optimalen Code

(Nun, ich gebe zu, dass dies mit abs ein bisschen künstlich ist, aber ich hoffe, Sie bekommen das Bild.)

    
Jens Gustedt 24.08.2010 12:10
quelle
1

Makros (erstellt mit #define ) werden immer wie geschrieben ersetzt und können Probleme bei der doppelten Auswertung haben.

inline dagegen ist rein beratend - der Compiler kann es ignorieren. Unter dem C99-Standard kann eine inline -Funktion auch eine externe Verknüpfung haben, die eine Funktionsdefinition erzeugt, mit der verlinkt werden kann.

    
caf 24.08.2010 08:09
quelle
1

Nun, eine mehrzeilige #define ist schwieriger zu schreiben und zu bearbeiten als eine Inline-Funktion. Sie können eine Inline-Funktion wie jede normale Funktion definieren und Variablen ohne Probleme definieren. Stellen Sie sich vor, Sie möchten einen Code-Block mehrmals innerhalb einer anderen Funktion aufrufen, und dieser Code-Block benötigt seine eigenen Variablen: Es ist einfacher mit Inline-Funktionen zu arbeiten (Ja, Sie können dies mit #defines und do { ... } while (0); tun, aber Sie sind es muss darüber nachdenken).

Außerdem erhalten Sie bei aktiviertem Debugging normalerweise einen "simulierten" Stack-Frame für Inline-Funktionen, der das Debuggen manchmal einfacher macht (zumindest erhalten Sie dies, wenn Sie mit% cc_de% von gcc kompilieren / verknüpfen und mit GDB debuggen). IIRC). Sie können Haltepunkte innerhalb Ihrer Inline-Funktion platzieren.

Abgesehen davon sollte das Ergebnis fast identisch sein, AFAIK.

    
DarkDust 24.08.2010 08:12
quelle
0

Der Unterschied ist hier ausführlich beschrieben: Ссылка Prost

    
tarrasch 24.08.2010 08:09
quelle
0

Funktionsähnliche Makros geben Ihnen an der Stelle, an der sie definiert sind, absolut keine Plausibilitätsprüfung. Wenn Sie ein Makro vermasseln, wird es an einem Ort gut funktionieren und woanders kaputt gehen, und Sie werden nicht wissen, warum, bis Sie mehrere Stunden Arbeit / Schlaf verloren haben. Funktionsähnliche Makros arbeiten nicht mit Daten, sie arbeiten mit Quellcode. Manchmal ist das gut, wenn Sie beispielsweise wiederverwendbare Debug-Anweisungen verwenden möchten, die FILE und LINE Builtins verwenden, aber meistens auch mit einem Inline-Befehl Funktion, die genau wie jede andere Funktion auf die Syntax am Definitionspunkt überprüft wird.

    
Chris 24.08.2010 09:01
quelle

Tags und Links