Sont des énoncés composés (blocs) entourés par des expressions de parens en ANSI C?

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

  •  11-09-2019
  •  | 
  •  

Question

Parcourir les sources du noyau Linux je trouve un morceau de code où un bloc d'instructions entouré par les parenthèses est traité comme une expression a la Lisp (ou ML), qui est, d'une expression dont la valeur est la valeur de la dernière déclaration.

Par exemple:

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

Je l'ai regardé ANSI grammaire C tente de comprendre comment ce morceau de code cadrerait dans l'arbre d'analyse syntaxique, mais je n'ai pas réussi.

Alors, est-ce que quelqu'un sait si ce comportement est mandaté par la norme ou est juste une particularité de GCC?

Mise à jour: Je l'ai essayé avec le drapeau -pedantic et le compilateur me donne maintenant un avertissement:

warning: ISO C forbids braced-groups within expressions
Était-ce utile?

La solution

Il est appelé "groupe contreventement dans les expression".

Il est pas autorisé par la norme ANSI / ISO C ++, mais ni C gcc supporte.

Autres conseils

Ce n'est pas valide C est une extension de gcc appelé expressions de déclaration , vous pouvez trouver la liste complète des extensions C ici . Ceci est en fait l'un des de nombreuses extensions gcc utilisées dans le noyau Linux et il semble que clang soutient cela aussi et bien qu'il ne soit pas explicitement nommé dans le document.

Comme vous avez observé la dernière expression sert de valeur de l'expression, le document dit ( Souligné par l'auteur ):

  

La dernière chose dans l'instruction composée doit être une expression suivie d'un point-virgule; la valeur de cette sous-expression sert de la valeur de la construction entière . (Si vous utilisez un autre type de déclaration dernière dans les accolades, la construction a le type vide, et donc effectivement aucune valeur.)

L'un des principaux avantages serait de faire sécurité macros permettant d'éviter plusieurs évaluations d'arguments avec des effets secondaires. L'exemple donné utilise cette macro dangereuse:

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

qui soit deux fois évalue a ou b et peut être réécrite pour éliminer ce problème en utilisant des expressions de déclaration comme suit:

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

Note, la nécessité d'utiliser explicitement int qui peut fixe en utilisant une autre extension gcc typeof :

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

Notez que clang soutient également typeof .

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