Les instructions composées (blocs) sont-elles entourées par des expressions parens dans ANSI C?

En parcourant les sources du kernel Linux, j’ai trouvé un morceau de code dans lequel un bloc d’instructions entouré de parenthèses est traité comme une expression à la mode (ou ML), c’est-à-dire une expression dont la valeur est la valeur de la dernière instruction.

Par exemple:

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

Je me suis penché sur la grammaire ANSI C pour essayer de comprendre comment ce morceau de code s’intégrerait dans l’arbre d’parsing, mais je n’ai pas réussi.

Alors, est-ce que quelqu’un sait si ce comportement est imposé par la norme ou s’il s’agit simplement d’une particularité de GCC?

Mise à jour: j’ai essayé avec la balise -pedantic et le compilateur me donne maintenant un avertissement:

 warning: ISO C forbids braced-groups within expressions 

C’est ce qu’on appelle “groupe contreventé dans l’expression”.

Ce n’est pas autorisé par ANSI / ISO C ni C ++ mais gcc le supporte.

Ceci n’est pas valide C c’est une extension gcc appelée expressions d’instruction , vous pouvez trouver la liste complète des extensions C ici . C’est en fait l’une des nombreuses extensions gcc utilisées dans le kernel Linux et il semble que clang le supporte aussi , bien qu’elle ne soit pas explicitement nommée dans le document.

Comme vous l’avez observé, la dernière expression sert de valeur à l’expression, le document ( souligné par moi ):

La dernière chose dans la déclaration composée devrait être une expression suivie d’un point-virgule; la valeur de cette sous-expression sert de valeur à la construction entière . (Si vous utilisez un autre type d’instruction en dernier entre accolades, la construction a le type void, et par conséquent aucune valeur.)

L’un des principaux avantages serait de créer des macros sécurisées qui éviteraient de multiples évaluations d’arguments ayant des effets secondaires. L’exemple donné utilise cette macro non sécurisée:

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

qui évalue a ou b deux fois et peut être réécrit pour éliminer ce problème en utilisant les expressions suivantes:

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

Notez la nécessité d’utiliser explicitement int qui peut être corrigé à l’aide d’une autre extension gcc Typeof :

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

Notez que clang prend également en charge le typeof .