Sind zusammengesetzte Anweisungen (Blöcke) in ANSI C von Klammerausdrücken umgeben?

Lesezeit: 3 Minuten

Benutzeravatar von fortran
Fortran

Beim Durchsuchen der Linux-Kernelquellen, die ich gefunden habe ein Stück Code wobei ein in Klammern eingeschlossener Anweisungsblock als Ausdruck behandelt wird a la lispeln (oder ML), das heißt, ein Ausdruck, dessen Wert der Wert der letzten Anweisung ist.

Zum Beispiel:

int a = ({
    int i;
    int t = 1;
    for (i = 2; i<5; i++) {
        t*=i;
    }
    t;
});

Ich habe mir die angeschaut ANSI-C-Grammatik Ich versuche herauszufinden, wie dieses Stück Code in den Parse-Baum passen würde, aber ich war nicht erfolgreich.

Weiß jemand, ob dieses Verhalten vom Standard vorgeschrieben ist oder nur eine Besonderheit von GCC ist?

Aktualisieren: Ich habe es mit dem Flag -pedantic versucht und der Compiler gibt mir jetzt eine Warnung:

warning: ISO C forbids braced-groups within expressions

Benutzeravatar von Shafik Yaghmour
Shafik Yaghmur

Dies ist kein Standard-C. Es ist eine gcc-Erweiterung namens Anweisungsausdrücke. Hier finden Sie die vollständige Liste der C-Erweiterungen hier. Dies ist tatsächlich einer der viele gcc-Erweiterungen, die im Linux-Kernel verwendet werden und es scheint so clang unterstützt dies auch und obwohl es im Dokument nicht explizit genannt wird.

Wie Sie beobachtet haben, dient der letzte Ausdruck als Wert des Ausdrucks, das Dokument sagt (Betonung von mir):

Das Das Letzte in der zusammengesetzten Anweisung sollte ein Ausdruck sein, gefolgt von einem Semikolon; der Wert dieses Unterausdrucks dient als Wert des gesamten Konstrukts. (Wenn Sie eine andere Art von Anweisung am Ende der geschweiften Klammern verwenden, hat das Konstrukt den Typ void und somit praktisch keinen Wert.)

Einer der Hauptvorteile wäre zu machen sicher Makros, die mehrfache Auswertungen von Argumenten mit Seiteneffekten vermeiden würden. Das angegebene Beispiel verwendet dieses unsichere Makro:

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

die entweder bewertet a oder b zweimal und kann umgeschrieben werden, um dieses Problem mit folgenden Anweisungsausdrücken zu beseitigen:

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

Beachten Sie, dass Sie explizit verwenden müssen int was mit einem anderen behoben werden kann gcc Verlängerung Art der:

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

Beachten Sie, dass clang unterstützt auch typeof.

  • Ist es möglich, ein Makro sicherheitshalber so ohne Anweisungsausdrücke zu schreiben?

    – Flimmer

    25. September 2014 um 14:38 Uhr

  • @Flimm Ich glaube nicht, aber ich würde mich nicht als Makroexperten bezeichnen. Ich vermeide sie so gut ich kann, obwohl es einige Fälle gibt, in denen sie schwer zu vermeiden sind, wie z. B. das Rollen Ihrer eigenen Behauptung.

    – Shafik Yaghmour

    26. September 2014 um 1:24 Uhr

  • @Flimm Das hängt davon ab, was Ihr Makro tun soll, in einigen Fällen ist es sicherlich möglich, ein sicheres Makro zu schreiben. Für das Komplette max Funktionalität werden Sie irgendwie zu kurz kommen, egal was Sie in Standard-C tun – das Problem ist, dass Sie entweder den Typ der Argumente kennen müssen oder eines davon zweimal auswerten müssen (wobei letzteres das Problem mit der ist Makroansatz oben).

    – Himmel König

    3. Mai 2017 um 13:17 Uhr

  • Hmpf, letzteres sollte modifiziert werden, um heterogene Argumente richtig zu unterstützen.

    – Deduplizierer

    4. August 2018 um 20:51 Uhr

Es heißt “verklammerte Gruppe innerhalb des Ausdrucks”.

Es ist weder in ANSI/ISO C noch in C++ erlaubt, aber gcc unterstützt es.

  • Sie können die Warnung in GCC durch Put unterdrücken __extension__ vor der öffnenden Klammer.

    – Flimmer

    25. September 2014 um 14:42 Uhr

  • @Flimm warum ist das keine Antwort?

    – hallo

    4. März 2020 um 13:55 Uhr

  • __extension__ hilft, aber NICHT, wenn die Anweisung im globalen Bereich verwendet wird

    – Sascha Itin

    29. Dezember 2020 um 11:17 Uhr


  • @hellow: Weil es das Problem nicht löst; es ist nur eine Tapete darüber.

    – Robert Harvey

    24. Januar 2021 um 20:01 Uhr

1403320cookie-checkSind zusammengesetzte Anweisungen (Blöcke) in ANSI C von Klammerausdrücken umgeben?

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

Privacy policy