10 Stimmen

Wie nennt man es, wenn ein Block einen Wert zurückgibt?

Ich bin kürzlich auf diesen Code gestoßen, der für mich nicht legal aussieht (aber gcc kompiliert ihn). Ich störe mich nicht so sehr an der Konstruktion, sondern möchte einen Namen dafür haben:

#define MAX(a,b) \
({ \
    typeof(a) _a = (a); \
    typeof(b) _b = (b); \
    (_a > _b) ? (_a) : (_b); \
})

Offenbar wird der Wert der letzten Anweisung als "Wert" des durch den Namensraum begrenzten Ausdrucks zurückgegeben.

Edit: Danke für die Antworten, Leute. Es stellt sich heraus, dass dies eine Erweiterung zu einfachem C namens Statement Expressions ist.

17voto

Alok Save Punkte 196241

Sie ist kein Namensraum , es ist ein Makro die das Maximum von zwei Werten zurückgibt.
\ am Ende der Anweisungen wird verwendet, um mehrere Anweisungen anzuhängen und ein mehrzeiliges Makro zu erstellen.

Der Code ist kein Standard-C++, aber er kompiliert in gcc, weil er als gcc-Compiler-Erweiterung .

Gute Lektüre:

Aussage Ausdrücke:
Eine zusammengesetzte Anweisung ist eine Folge von Anweisungen, die von geschweiften Klammern umgeben sind. In GNU C kann eine zusammengesetzte Anweisung innerhalb von Klammern als Ausdruck in einem so genannten Statement expression .

         .--------------.
         V              |
>>-(--{----statement--;-+--}--)--------------------------------><

Der Wert eines Anweisungsausdrucks ist der Wert des letzten einfachen Ausdrucks, der in dem gesamten Konstrukt vorkommt. Wenn die letzte Anweisung kein Ausdruck ist, ist das Konstrukt vom Typ void und hat keinen Wert.

Hinweis: Dieser Auszug stammt aus der IBM XL C/C++ v7.0 Dokumentation.

7voto

Mike Seymour Punkte 242473

Dies wird als Anweisungsausdruck und ist ein Nicht-Standard Erweiterung des GCC. Sie ermöglicht es Ihnen, eine zusammengesetzte Anweisung als Ausdruck zu verwenden, wobei der Wert durch den letzten Ausdruck in der zusammengesetzten Anweisung gegeben ist.

Es wird hier verwendet, um das Problem zu vermeiden, dass funktionsähnliche Makros ihre Argumente mehrfach auswerten können, was zu unerwartetem Verhalten führt, wenn diese Auswertungen Nebenwirkungen haben. Das Makro ist sorgfältig geschrieben, um Folgendes auszuwerten a y b genau einmal.

In C++ sollten Sie so etwas nie tun müssen - verwenden Sie stattdessen Funktionsvorlagen:

template <typename T> T max(T const & a, T const & b) {
    return a > b ? a : b;
}

4voto

Craig Reynolds Punkte 575

Dies kann als Off-Topic gesehen werden, aber der Titel dieser Frage kam in meiner Web-Suche bei der Suche nach einem Weg, um einen Wert aus einer {} blockieren. Dann wurde mir klar, wie man das mit Standard-C++-Konstrukten machen kann. Ich poste dies für die nächste Person, die aus demselben Grund hier landet.

Um aufzugreifen, was @BRPocock sagte vor 8 Jahren, dass es ist möglich, einen Wert aus einem "anonymen Bereichsoperator" / "lexikalischen Gehäuse" zurückzugeben - verwenden Sie daher ein {} Blocks als Teil eines Ausdrucks - durch die Verwendung von Lambda-Funktionen .

(Historische Anmerkung: Alle Bindungsformen in Lisp können in Form von Makros mit Lambda-Ausdrücken geschrieben werden. Von Lisp stammt der moderne Begriff "Lambda-Funktion". Lisp war 1959 John McCarthys prozedurale Verkörperung des theoretischen "Lambda-Kalküls" von Church und Turning).

Zurück zu C++, dies ist eine minimale anonyme Lambda-Funktion, ohne lexikalische Erfassung, ohne Argumente und mit leerem Körper:

[](){}

Dies ist die Funktion, die auf keine Argumente angewendet wird:

[](){}()

Hier ist der Funktionsaufruf mit einigen Anweisungen in seinem Körper:

[](){ int i=2; int j=3; return i+j; }()

Drumherum gibt es einige zusätzliche "Dinge" (die pourrait mit einem Makro gekapselt werden) und erfordert die ausdrückliche Verwendung von return aber es erfüllt die grundlegende Funktion der Rückgabe eines Wertes aus einer {} Block. Zum Beispiel wird hier 5 gedruckt:

std::cout << [](){ int i=2; int j=3; return i+j; }() << std::endl;

2voto

Nawaz Punkte 339767

Zunächst einmal handelt es sich nicht um Standard-C++, denn typeof ist eine Erweiterung von C++ durch den GCC. Es gibt eine weitere Erweiterung, die Statement Extension, die im Code verwendet wird.

Kompilieren Sie Ihren Code mit -pedantic wird es nicht kompiliert.

Was die Frage betrifft, so handelt es sich nicht um einen Namespace. Es ist nur ein Makro, das Ihnen maximal zwei Werte gibt.

1voto

Stealth Rabbi Punkte 9776

Dies ist ein Makro, genau wie jedes andere #DEFINE. Im Wesentlichen ersetzt der Compiler MAX(a,b) durch den darin definierten Code. Dieser gibt den Maximalwert zurück.

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