Was ist der praktische Unterschied zwischen Inline und #define?

Lesezeit: 4 Minuten

eliegos Benutzeravatar
eligo

Wie der Titel sagt; Was ist in der Praxis der Unterschied zwischen dem Schlüsselwort inline und der Präprozessordirektive #define?

  • mögliches Duplikat von Inline-Funktionen vs. Präprozessor-Makros

    – jww

    28. Juli 2014 um 17:57 Uhr

Benutzeravatar von Pavel Radzivilovsky
Pavel Radzivilovsky

#define ist ein Präprozessor-Tool und hat eine Makrosemantik. Betrachten Sie dies, wenn max(a,b) ist ein Makro, definiert als

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

Beispiel 1:

val = max(100, GetBloodSample(BS_LDL)) würde zusätzliches unschuldiges Blut vergießen, da die Funktion tatsächlich zweimal aufgerufen wird. Dies kann für reale Anwendungen einen erheblichen Leistungsunterschied bedeuten.

Beispiel 2:

val = max(3, schroedingerCat.GetNumPaws())

Dies demonstriert a gravierender Unterschied in der Programmlogikda dies unerwartet eine Zahl zurückgeben kann, die kleiner als 3 ist – etwas, das der Benutzer nicht erwarten würde.

Beispiel 3:

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


Bei Inline-Funktionen passiert nichts davon.

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

  • Du solltest dich ändern shroedingerCat.GetNumPaws() eine C-Funktion sein, nicht C++.

    – Alternative

    24. August 2010 um 11:17 Uhr

  • Nun, die Frage betrifft C; Es ist jedoch üblicher, dass C++-Memberfunktionen von Zeit zu Zeit unterschiedliche Dinge zurückgeben, da sie sich natürlich auf den Zustand ihres Objekts verlassen.

    – Pavel Radzivilovsky

    24. August 2010 um 14:41 Uhr

  • Thx für die tolle Antwort mit tollen Beispielen =)

    – eligo

    25. August 2010 um 20:55 Uhr

  • Ich sehe keinen Unterschied zwischen Ex1 und Ex2, Sie rufen max auf zwei verschiedenen Werten auf.

    – David 天宇 Wong

    28. Dezember 2016 um 20:35 Uhr

  • Der Unterschied besteht darin, dass #define max() nicht berechnet, sondern stattdessen sehr schlechte Dinge tut.

    – Pavel Radzivilovsky

    30. Dezember 2016 um 9:26 Uhr

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

Makros sind Textersetzungen, die zur Kompilierzeit durchgeführt werden, und sie können Dinge tun wie

#define P99_ISSIGNED(T) ((T)-1 < (T)0)

Dadurch erhalten Sie einen Ausdruck zur Kompilierungszeit, ob ein ganzzahliger Typ signiert ist oder nicht. Das heißt, sie werden idealerweise verwendet, wenn der Typ eines Ausdrucks (bei der Definition) nicht bekannt ist und Sie etwas dagegen tun möchten. Auf der anderen Seite besteht die Gefahr bei Makros darin, dass ihre Argumente möglicherweise mehrmals ausgewertet werden, was aufgrund von Nebenwirkungen nachteilig ist.

Funktionen (inline) andererseits sind typisiert, was sie strenger oder negativ formuliert weniger flexibel macht. Betrachten Sie die Funktionen

inline uintmax_t absU(uintmax_t a) { return a; }
inline uintmax_t absS(uintmax_t a) {
   return (-a < a) ? -a : a;
}

Die erste implementiert das Triviale abs Funktion für einen ganzzahligen Typ ohne Vorzeichen. Die zweite implementiert es für einen signierten Typ. (Ja, es braucht ein unsigned als Argument, das ist beabsichtigt.)

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ählt.

Nun mit folgendem Makro

#define ABS(T, A) ((T)(P99_ISSIGNED(T) ? absS : absU)(A))

Wir haben eine implementiert

  • Familie von Funktionen
  • das funktioniert für jeden ganzzahligen Typ
  • die ihr Argument nur einmal auswertet
  • für die jeder neuere und anständige Compiler optimalen Code erstellt

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

Makros (erstellt mit #define) werden immer wie geschrieben ersetzt und können Doppelauswertungsprobleme haben.

inline auf der anderen Seite ist rein beratend – der Compiler kann es ignorieren. Unter dem C99-Standard wird an inline Die Funktion kann auch eine externe Verknüpfung haben, wodurch eine Funktionsdefinition erstellt wird, mit der verknüpft werden kann.

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 können problemlos Variablen definieren. Stellen Sie sich vor, Sie möchten einen Codeblock mehrmals innerhalb einer anderen Funktion aufrufen, und dieser Codeblock benötigt seine eigenen Variablen: Dies ist einfacher mit Inline-Funktionen (ja, Sie können dies mit #defines und tun do { ... } while (0); aber das muss man sich überlegen).

Außerdem erhalten Sie bei aktiviertem Debugging normalerweise einen “simulierten” Stack-Frame für Inline-Funktionen, was das Debuggen manchmal einfacher machen könnte (zumindest erhalten Sie das, wenn Sie mit gcc’s kompilieren/linken -g und debuggen mit GDB, IIRC). Sie können Haltepunkte innerhalb Ihrer Inline-Funktion platzieren.

Abgesehen davon sollte das Ergebnis fast identisch sein, AFAIK.

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 einer Stelle gut funktionieren und an einer anderen kaputt sein, und Sie werden nicht wissen warum, bis Sie mehrere Stunden Arbeit/Schlafzeit verloren haben. Funktionsähnliche Makros arbeiten nicht mit Daten, sie arbeiten mit Quellcode. Manchmal ist dies gut, wenn Sie beispielsweise wiederverwendbare Debug-Anweisungen verwenden möchten DATEI Und LINIE builtins, aber meistens geht es genauso gut mit einer Inline-Funktion, die wie jede andere Funktion zum Zeitpunkt der Definition auf Syntax geprüft wird.

1444130cookie-checkWas ist der praktische Unterschied zwischen Inline und #define?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy