Makros V/S Inline-Funktionen während der Programmierung für avr-gcc

Ich habe in diesen Tagen meine erste ernsthafte Programmierarbeit gemacht. Ich wurde mit einer Menge Code von verschiedenen Entwicklern konfrontiert. Eine Sache, die ich verwirrend finde, ist, wie diese Entwickler entscheiden, wann sie eine Makrodefinition und wann eine Inline-Funktion verwenden. Beide haben im Wesentlichen die gleiche Funktion, sie platzieren einen bestimmten Code an der Stelle, von der aus sie aufgerufen werden. Gibt es also eine Logik für die Auswahl oder ist es nur eine Laune des Entwicklers?

(Ich spreche hier von Makros für Funktionen und nicht für Konstanten).

Möglicherweise erhalten Sie detailliertere Antworten von stackoverflow auf diese Art von Frage.
Ich hatte darüber nachgedacht, es dort zu posten, aber ich dachte, da dies spezifischer für eingebettete Systeme wäre, sollte ich es hier posten.

Antworten (2)

Es gibt viele Vorteile von Inline-Funktionen gegenüber Präprozessor-Makros:

  • Typüberprüfung . Der Compiler wird sich beschweren, wenn die Argumente vom falschen Typ sind.
  • Kein Risiko einer Mehrfachauswertung : Makros können gefährlich sein, wenn das Argument ein Ausdruck ist, beachten Sie:

    #include <stdio.h>
    #define square(n) ((n)*(n))
    
    int main(void)
    {
        int x, i = 0;
        while (i < 10) {
            x = square(i++);
            printf("%d\r\n", x);
        }
        return 0;
    }
    
  • Kann mehrere Codezeilen ohne abschließende Backlashes enthalten.
  • Inline-Funktionen haben ihren eigenen Gültigkeitsbereich für Variablen und können einen Wert zurückgeben .

Makros können zB beim Verketten von Tokens in Code nützlich sein, um einige komplexe Deklarationen zu vereinfachen.

Betrachten Sie Makros einfach als eine dumme Textersetzungsfunktion. Eine gute Faustregel ist, funktionsähnliche Makros zu vermeiden, es sei denn, es gibt keine andere praktikable Lösung .

Es ist ein weit verbreiteter Irrglaube, dass Inlining immer schnelleren Code bedeutet. Denken Sie daran, dass sich jeder Inline-Aufruf von mehr als einer Stelle zur Codegröße summiert . Voreilige Optimierung ist keine Tugend, selbst wenn man mit den begrenzten Ressourcen eines Mikrocontrollers arbeitet.

GCC interpretiert das inlineSchlüsselwort als bloßen Hinweis. Es gibt keine Garantie dafür, dass die Funktion tatsächlich eingebettet wird. Damit GCC Ihre Funktion unabhängig von der Optimierungsstufe integriert, deklarieren Sie die Funktion mit dem always_inlineAttribut:

void function() __attribute__((always_inline));

Inline-Funktionen können vom Compiler eingebunden werden oder nicht. Makros hingegen werden vom Precompiler behandelt und sind daher garantiert inline (Code repliziert). Oft verwendet man ein Makro für eine kurze, aber komplexe Operation, um den Code lesbarer zu machen, ohne einen Funktionsaufruf in Kauf zu nehmen. Zum Beispiel:

#define SWAP(a,b)({a ^= b; b ^= a; a ^= b;})

... bietet eine Möglichkeit, die Variablen a und b ohne Funktionsaufruf und ohne temporäre Variable zu vertauschen.

Es gibt eine Stackoverflow-Frage mit dem gleichen Effekt (allerdings nicht speziell über avr-gcc).