Syntaktischer Zucker in C/C++

Lesezeit: 8 Minuten

Benutzer-Avatar
BiGYaN

Ich habe mich mit Ruby beschäftigt und finde die Schlüsselwörter „until“ und „unless“ sehr interessant. Also dachte ich, was eine gute Möglichkeit wäre, ähnliche Schlüsselwörter in C/C++ hinzuzufügen. Das ist mir eingefallen:

#define until(x)    while(!(x))
#define unless(x)   if(!(x))

Ich suche hierzu ein paar Anregungen. Kann jemand eine bessere Alternative vorschlagen?

Hier ist ein Beispiel für ein Programm, das ich geschrieben habe, um zu veranschaulichen, was ich vorhatte:

#include <stdio.h>
#include <stdlib.h>

#define until(x)    while(!(x))
#define unless(x)   if(!(x))

unsigned int factorial(unsigned int n) {
    unsigned int fact=1, i;
    until ( n==0 )
        fact *= n--;
    return fact;    
}

int main(int argc, char*argv[]) {
    unless (argc==2)
        puts("Usage: fact <num>");
    else {
        int n = atoi(argv[1]);
        if (n<0)
            puts("please give +ve number");
        else
            printf("factorial(%u) = %u\n",n,factorial(n));
    }
    return 0;
}

Es wäre großartig, wenn Sie mir einige Referenzen für ähnliche Tricks nennen könnten, die in C oder C++ eingesetzt werden können.

  • Es scheint, als hättest du es bereits getan.

    – Thiago Cardoso

    9. April 2011 um 19:26 Uhr

  • Obwohl diese auf den ersten Blick sehr schick aussehen, ist es angemessener, stattdessen Standard-C++ zu verwenden, auch wenn Sie nur für sich selbst programmieren. In der Teamarbeit ist das ein No-Go. Ihr Code wird ungewohnt aussehen. Ich erinnere mich an eine bestimmte sugar.h enthält Pascal-ähnliche Definitionen …

    – mbx

    9. April 2011 um 19:27 Uhr


  • Ich glaube nicht, dass ich mag unless mit einem else -Klausel (ich liebe es jedoch, wenn/es sei denn beim Lispeln). Ich bin nicht wirklich beeindruckt von einem until Schleife, kann aber daran liegen, dass ich sie noch nie zuvor benutzt habe.

    – 6502

    9. April 2011 um 19:42 Uhr

  • Dieses Projekt könnte Sie interessieren: lolcode.com die auch etwas syntaktischen Zucker hinzufügen … 😀

    – Invers

    21. April 2011 um 20:57 Uhr

  • Wenn Sie dies tun müssen, ist mein einziger Vorschlag, zu buchstabieren until richtig.

    – Zach Rattner

    22. April 2011 um 14:40 Uhr

Benutzer-Avatar
James McNellis

Kann jemand eine bessere Alternative vorschlagen?

Ja. Tun Sie dies auf keinen Fall. Verwenden Sie einfach die while und if Aussagen direkt.

Wenn Sie in C oder C++ programmieren, programmieren Sie in C oder C++. Während until und unless in einigen Sprachen häufig und idiomatisch verwendet werden, sind sie nicht in C oder C++.

  • +1 dazu. Es mag idiomatisch sein, dies in Ruby zu tun, aber Sie programmieren nicht in Ruby, oder? Versuchen Sie nicht, eine Sprache dazu zu zwingen, sich wie eine andere zu verhalten, Sie werden auf diese Weise nur schlechten Code schreiben.

    – Mike Bailey

    9. April 2011 um 19:29 Uhr

  • Ich weiß, dass in einer großen Umgebung Codierung wie diese nur Ärger hervorrufen wird. Aber meine Frage war, wie ich das am besten mache; und nicht darüber, ob man das tun soll oder nicht.

    – BiGYan

    10. April 2011 um 6:57 Uhr

  • @BiGYaN: Der beste Weg, dies zu tun, besteht darin, dies überhaupt nicht zu tun.

    – James McNellis

    10. April 2011 um 7:31 Uhr


  • Das ist !nützlich.

    – n-Schläge

    13. Juli 2020 um 21:34 Uhr

Benutzer-Avatar
Jack v.

Die Art und Weise, wie Sie es getan haben, scheint mir die richtige zu sein, wenn Sie es überhaupt tun wollen. Denn die Erweiterung des Makros ist Also ähnlich wie Sie es erwarten würden[1]ich denke, es ist richtig, das Makro wie syntax () aussehen zu lassen, anstatt wie die normalerweise empfohlenen SCARY_UPPERCASE_MACROS(), die verwendet werden, um zu zeigen, dass dieser Code nicht der üblichen Syntax folgt und Sie ihn nur vorsichtig verwenden sollten.

[1] Der einzige Fehler ist die Unfähigkeit, Variablen zu deklarieren, was sowieso unwahrscheinlich ist und bei falscher Verwendung wahrscheinlich einen Fehler an der richtigen Stelle erzeugt, anstatt etwas Seltsames zu tun.

Darüber hinaus sind auch kleine Steigerungen der Lesbarkeit wichtig, so kann man sagen until ( Anstatt von while (! macht es wirklich einfacher, viele Schleifen zu lesen. Wenn die Endbedingung leichter als Ausnahmebedingung angesehen werden kann (unabhängig davon, ob dies der Fall ist oder nicht), erleichtert das Schreiben der Schleife in dieser Richtung das Lesen. Obwohl es also nur syntaktischer Zucker ist, denke ich, dass es Grund gibt, darüber nachzudenken.

Jedoch Ich glaube nicht, dass es das wert ist. Der Nutzen ist gering, da die meisten Programmierer ans Lesen gewöhnt sind if (! und die Kosten sind real: Jeder, der den Code liest, muss prüfen, ob es sich um ein Makro oder einen benutzerdefinierten Compiler handelt und ob er das tut, was er denkt. Und es kann Sie fälschlicherweise glauben machen, dass Sie Dinge tun können wie i=5 unless xxxx;. Solche kleinen Verbesserungen würden, wenn sie weit verbreitet wären, die Sprache fragmentieren, daher ist es oft am besten, die Dinge auf die übliche Weise zu tun und Verbesserungen langsam anzunehmen.

Es kann jedoch gut gemacht werden: Die Gesamtheit von boost und tr1, insbesondere das Zeug, das mit Templates gemacht wird, um wie Erweiterungen der Bibliothek auszusehen, beinhaltet das Erweitern von C++ auf verschiedene Arten, von denen viele nicht übernommen werden, da sie sich nicht lohnen es, aber viele davon haben eine geringe oder sehr weit verbreitete Akzeptanz, weil sie echte Verbesserungen gebracht haben.

  • Der erste Absatz dieser Antwort ist, gelinde gesagt, problematisch! Makros haben keinen Namensraum; sie sind total global. So ist es abscheulich um ihnen Kurznamen zu geben, die woanders verwendet werden könnten. Wenn Sie ein Makro mit einem kurzen Namen wie z untilund dann fügen Sie einen Header eines Drittanbieters ein, der eine Memberfunktion deklariert until, wird dieser Header beschädigt. Es wird versuchen zu erklären void until(int a); sondern wird stattdessen sagen void while(!(int a)); Viel Glück beim Entschlüsseln dieser Fehlermeldung! Und so verwendet Boost (wenig überraschend) gruselige Namen in Großbuchstaben mit Präfixen für all seine Makrotricks.

    – Daniel Earwicker

    11. November 2013 um 12:31 Uhr

Das erinnerte mich an etwas, das ich in jemandes Code gesehen habe:

#define R return;

Außerdem erhöhen Sie die Wartungskosten, indem Sie den Code schwer verständlich machen.

Ich schlage vor, es wäre besser, sie nicht zu verwenden.

Sie können sie nicht im Ruby-Stil verwenden

`printf("hello,world") unless(a>0);`

ist illegal.

Und für C-Programmierer wäre es schwieriger, den Code zu verstehen. In der Zwischenzeit könnte das zusätzliche Makro ein Problem sein.

Wenn Sie Makros definieren, ist es eine gute Praxis, sie wirklich hässlich aussehen zu lassen. Insbesondere sollten sie nur aus Großbuchstaben bestehen und eine Art Präfix haben. Dies liegt daran, dass es keine Namensräume und keine Koordination mit dem Typsystem oder der Überladungsauflösung von C++ gibt.

Also wenn dein Makro aufgerufen wurde BIGYAN_UNNECESSARY_MACRO_UNTIL dann wäre es nicht ganz “jenseits”.

Wenn Sie C++ mit neuen Schleifenkonstrukten erweitern möchten, sollten Sie Lambdas in C++0x untersuchen, wo Sie Folgendes zulassen könnten:

until([&] { return finished; }, [&] 
{
    // do stuff
});

Es ist nicht perfekt, aber es ist besser als Makros.

  • Ihre vorgeschlagene Verwendung von Lambdas dafür wird mir heute Nacht Alpträume bereiten

    – 6502

    9. April 2011 um 19:39 Uhr

  • Ich bin in Konflikt geraten: Diese Verwendung von Lambdas ist gleichzeitig schrecklich und großartig. Ich mag es aber.

    – James McNellis

    9. April 2011 um 19:57 Uhr

  • Für etwas so Einfaches wie die Neuimplementierung while(!b) es ist eindeutig übertrieben.

    – Daniel Earwicker

    9. April 2011 um 20:01 Uhr

  • Es ist in der Tat schrecklich und großartig. Dies ist jedoch ganz normaler Code (und ziemlich sauber) in FP-Sprachen. Die Möglichkeit, eine eigene Kontrollstruktur zu definieren, ist sehr, sehr nützlich.

    – ysdx

    9. April 2011 um 23:45 Uhr

Ich denke nicht, dass Ihre Makros besonders schlecht sind, wenn sie nur in Ihrer eigenen Codebasis verwendet werden.
Dieser Artikel
könnte für dich interessant sein. Davon abgesehen sehe ich einige Nachteile in Ihren Makros, wenn wir sie in C++ verwenden.
Zum Beispiel können wir nicht schreiben als:

until (T* p = f(x)) ...
unless (T* p = f(x)) ...

andererseits können wir schreiben als:

while (T* p = f(x)) ...
if (T* p = f(x)) ...

Wie für unlesswenn wir es definieren als:

#define unless(x) if (x) {} else

dann können wir schreiben unless (T* p = f(x)) .... In diesem Fall können wir jedoch nicht hinzufügen else Klausel danach.

  • Ihre vorgeschlagene Verwendung von Lambdas dafür wird mir heute Nacht Alpträume bereiten

    – 6502

    9. April 2011 um 19:39 Uhr

  • Ich bin in Konflikt geraten: Diese Verwendung von Lambdas ist gleichzeitig schrecklich und großartig. Ich mag es aber.

    – James McNellis

    9. April 2011 um 19:57 Uhr

  • Für etwas so Einfaches wie die Neuimplementierung while(!b) es ist eindeutig übertrieben.

    – Daniel Earwicker

    9. April 2011 um 20:01 Uhr

  • Es ist in der Tat schrecklich und großartig. Dies ist jedoch ganz normaler Code (und ziemlich sauber) in FP-Sprachen. Die Möglichkeit, eine eigene Kontrollstruktur zu definieren, ist sehr, sehr nützlich.

    – ysdx

    9. April 2011 um 23:45 Uhr

Benutzer-Avatar
Thorsten

Gutes Beispiel für Syntaxzucker (IMHO):

struct Foo {
    void bar() {}
};
typedef std::vector<Foo*> FooVector;
typedef boost::ptr_vector<Foo> FooPtrVector;

FooVector v1;
for (FooVector::iterator it = v1.begin(); it != v1.end(); ++it)
    (*it)->bar(); // ugly

FooPtrVector v2;
for (FooPtrVector::iterator it = v2.begin(); it != v2.end(); ++it)
    it->bar(); // nice

1384150cookie-checkSyntaktischer Zucker in C/C++

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

Privacy policy