Warum würden Sie verwenden, um den ternären Operator ohne einen Wert für den „wahren“ Zustand zuweisen (x = x: 1)

StackOverflow https://stackoverflow.com/questions/2806255

Frage

In dem Android Open-Source-Code qemu ich auf dieser Codezeile lautete:

machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */

Ist das nur eine verwirrende Art zu sagen:

if (machine->max_cpus) {
   ; //do nothing
} else {
 machine->max_cpus = 1;
}

Wenn ja, wäre es nicht klarer sein als:

if (machine->max_cpus == 0) machine->max_cpus = 1;

Interessanterweise ist diese kompiliert und funktioniert gut mit gcc, aber nicht kompiliert auf http: //www.comeaucomputing .com / tryitout / .

War es hilfreich?

Lösung

Dies ist erlaubt in GNU als eine obskure Erweiterung auf C

  

5.7 Conditionals mit weggelassenen Operanden

     

Der mittlere Operanden in einem bedingten   Ausdruck kann weggelassen werden. Dann, wenn die   erster Operand ungleich Null ist, sein Wert ist   der Wert der bedingten   Ausdruck.

     

Daher ist der Ausdruck

 x ? : y
     

hat den Wert von x, wenn das nicht Null ist;   andernfalls wird der Wert von y.

     

Dieses Beispiel ist vollkommen gleichwertig   zu

 x ? x : y
     

In diesem einfachen Fall die Fähigkeit,   omit der mittlere Operand nicht   besonders nützlich. Wenn es wird   nützlich ist, wenn der erste Operand der Fall ist,   oder kann (wenn es sich um eine Makro-Argument ist),   enthält eine Nebenwirkung. dann Wiederholung   der Operand in der Mitte würde   zuführen zweimal den Nebeneffekt.   Das Weglassen des mittleren Operand verwendet die   Wert bereits ohne die berechneten   unerwünschte Wirkungen von recomputing es.

Wie Sie wahrscheinlich erraten kann, dies zu vermeiden ist, um die Lesbarkeit und Portabilität Gründen empfohlen. Ich bin überrascht, ehrlich, eine solche Grammatik-inkompatiblen Erweiterung C sehen

Andere Tipps

Dies ist ein GCC-Erweiterung das bedeutet " wenn die Bedingung erfüllt ist, verwenden sie es, sonst diesen anderen Wert verwenden“, so

machine->max_cpus = machine->max_cpus ?: 1;

ist eine Abkürzung für

machine->max_cpus = machine->max_cpus ? machine->max_cpus : 1;

obwohl, wenn die bedingten Nebenwirkungen hat, wird es nur einmal ausgeführt werden

Mit gcc -pedantic Flagge, es sagt

  

foo.c: 5: Warnung: ISO C verbietet   die mittlere Laufzeit von einem Weglassen?:   Ausdruck

Es ist eine GCC Erweiterung , und es wird mehr interessant und nützlich, wenn die Bedingung Nebenwirkungen hat.

In diesem Fall ja, denn ich würde man zustimmen es ist unklar mehr als alles andere.

Die K & R BNF zeigt ein Ausdruck erforderlich, um zwischen "?" und ":". Ich glaube nicht, gcc sollte ohne Diagnose, dass kompilieren.

Es gibt einen weiteren nützlichen Fall für diese - die Eliminierung von Zwischenvariablen, wenn eine Funktion oder eine Methode aufrufen, die Null zurückkehren könnte, dass wir zweimal Aufruf vermeiden wollen. Zum Beispiel (Objective-C) an, dass wir eine Datei in eine Array entpacken wollen, wenn es vorhanden ist, sonst ein leeres Array zurück.

- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
    NSArray *backlog = @[];
    NSData *backlogData = [NSData dataWithContentsOfFile:path];
    if (backlogData)
    {
        backlog = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData] ?: backlog;
    }
    return backlog;
}

Die Alternativen sind weniger prägnant.

- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
    NSArray *backlog = @[];
    NSData *backlogData = [NSData dataWithContentsOfFile:path];
    if (backlogData)
    {
        NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData];
        if (tempArray != nil)
        {
            backlog = tempArray;
        }
    }
    return backlog;
}

oder hässlicher mit mehreren kehrt etc.

- (NSArray*)hydrateBacklogFromFile:(NSString *path)
{
    NSData *backlogData = [NSData dataWithContentsOfFile:path];
    if (backlogData)
    {
        NSArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithData:backlogData];
        if (tempArray != nil)
        {
            return tempArray;
        }
    }
    return @[];
}

So ist es sinnvoll syntaktischer Zucker ist, dass ich ziemlich lesbar zu finden. Die Nachteile sind

  • Die implizite Konvertierung eines Zeigers auf einem Bool. Dies ist eine seit langem bestehende C Konvention, aber die meisten modernen Sprachen verbieten es, verkompliziert kein Portierungsaufwand.

  • Wie schon andere gesagt haben, es ist auch eine Nicht-Standard-Erweiterung, so sollte es vermieden werden, wenn Portabilität eine Überlegung überhaupt ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top