4 Stimmen

Wie erstellt man ein Makro mit mehreren Codezeilen?

Ich möchte ein Makro zu machen, die einige Code, wie injizieren wird:

if (foo) {
[Bar fooBar];
}

und dann, wo immer ich das brauche, füge ich FOOBAR in den Code ein. Ich bin mir nicht sicher, aber zur Kompilierzeit ersetzt der Compiler dies durch den tatsächlichen Code wie im obigen Beispiel. Vielleicht gibt es etwas anderes als ein Makro, das ich dafür verwenden könnte?

10voto

Peter Hosey Punkte 94684

Verwenden Sie \, um jeden Zeilenumbruch, der Teil des Makros sein soll, zu umgehen.

Seien Sie sich jedoch bewusst, dass die Verwendung von Makros wie diesem die Struktur verbergen kann, wenn Sie nicht vorsichtig sind. Nehmen wir Ihr Beispiel:

if (bar)
    FOOBAR();
else
    do_something_else();

Raten Sie mal, worauf das hinausläuft. Wahrscheinlich nicht das, was Sie denken. Hier ist, was der Compiler sieht (Einrückung angepasst):

if (bar)
    if (foo)
        {
            [Bar fooBar];
        }
;
    else
        do_something_else();

Huch! Das Semikolon ist eine separate, leere Aussage. Jede if benötigt nur eine Anweisung; die erste if ist die zweite Aussage des if und die zweite if Die Anweisung der Kommission ist die zusammengesetzte Anweisung ( {…} ), so dass sie beide ihre Quote erfüllt haben, wobei das Semikolon weggelassen wurde.

Das Semikolon ist also nicht an eine if -Sie ist bedingungslos. Das führt zu einem Syntaxfehler, wenn Sie dann versuchen, die else zu einer unbedingten Aussage.

Die Lösung, so hässlich sie auch ist, besteht darin, den Inhalt von FOOBAR in einem do…while Erklärung:

#define FOOBAR()       \
    do {                \
        if (foo)         \
            [Bar fooBar]; \
    } while(0) /*semicolon omitted*/

Da wir das Semikolon in der Makrodefinition weglassen, wird die do…while ist eine nicht beendete Anweisung, so dass das Semikolon außerhalb der Makroverwendung an sie gebunden wird. Dann sieht unser erweiterter Code wie folgt aus:

//First, the unexpanded code again
if (bar)
    FOOBAR();
else
    do_something_else();

//Expanded
if (bar)
    do
        {
            if (foo)
                [Bar fooBar];
        }
    while(0);
else
    do_something_else();

En else bindet nun an if (bar) wie Sie es beabsichtigt haben.

6voto

Mark Ransom Punkte 283960

Sie können definieren. ein Makro auf mehreren Zeilen, indem Sie am Ende jeder Zeile außer der letzten ein \ anhängen. Leider wird das Makro auf eine einzige Zeile erweitert, wenn Sie es tatsächlich verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X