Pourquoi utiliser l'opérateur ternaire sans attribuer une valeur pour la condition « true » (x = x: 1)

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

Question

Dans le code qemu open-source Android je suis tombé sur cette ligne de code:

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

Est-ce juste une façon déroutante de dire:

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

Dans ce cas, ne serait-il plus clair que:

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

Fait intéressant, cette compile et fonctionne très bien avec gcc, mais ne compile pas sur http: //www.comeaucomputing .com / tryitout / .

Était-ce utile?

La solution

autorisé GNU une extension obscure à C

  

5.7 Conditionals avec Opérandes Omission

     

L'opérande milieu dans un conditionnel   expression peut être omise. Ensuite, si le   premier opérande est non nul, sa valeur est   la valeur du conditionnel   expression.

     

Par conséquent, l'expression

 x ? : y
     

a la valeur de x est différent de zéro si cela;   autrement, la valeur de y.

     

Cet exemple est tout à fait équivalent   à

 x ? x : y
     

Dans ce cas simple, la capacité de   omettent l'opérande du milieu est pas   particulièrement utile. Quand il devient   utile est lorsque le premier opérande fait,   ou peut (si elle est un argument macro),   contenir un effet secondaire. puis répéter   l'opérande au milieu serait   exécuter l'effet secondaire à deux reprises.   Omettre l'opérande milieu utilise la   valeur déjà calculée sans   effets indésirables de recalcul il.

Comme vous pouvez probablement le deviner, en évitant ce qui est recommandé pour des raisons de lisibilité et de portabilité. Je suis honnêtement surpris de voir une telle extension incompatible avec la grammaire à C.

Autres conseils

Ceci est un extension de GCC signifie " si la condition est vraie, l'utiliser, utilisez autre cette autre valeur », donc

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

est un raccourci pour

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

bien que si le conditionnel a des effets secondaires, il ne sera exécuté qu'une seule fois

En utilisant le drapeau -pedantic de gcc, il ne dit

  

foo.c: 5: avertissement: ISO défend C   en omettant le moyen terme d'un?:   expression

Il est un extension GCC , et devient plus intéressant et utile lorsque l'état a des effets secondaires.

Dans ce cas, oui, je suis d'accord pour une obscure il est plus que toute autre chose.

Le K & R BNF montre une expression est nécessaire entre "?" et ":". Je ne pense pas que gcc devrait compilera que sans diagnostic.

Il y a un autre cas utile pour cela - l'élimination des variables intermédiaires lors de l'appel d'une fonction ou d'une méthode qui pourrait revenir à zéro, que nous voulons éviter d'appeler deux fois. Par exemple (Objective-C), supposons que nous voulions décompresser un fichier dans un tableau si elle existe, sinon retourner un tableau vide.

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

Les alternatives sont moins concis.

- (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;
}

Ou plus laid avec de multiples retours etc.

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

Il est donc utile de sucre syntaxique que je trouve assez lisible. Les inconvénients sont

  • La conversion implicite d'un pointeur vers un bool. Ceci est un C de longue date convention, mais la plupart des langues modernes désavouer, ce qui complique tout effort de portage.

  • Comme d'autres l'ont dit est aussi une extension non standard, il devrait donc être évitée si la portabilité est une considération du tout.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top