J'ai trouvé ce morceau de code sur GitHub mais je ne l'ai pas bien compris:
#define lambda(ret_type, _body) ({ ret_type _ _body _; })
Alors:
int (*max)(int, int) = lambda(int,
(int x, int y) {
return x > y ? x : y;
});
int max_value = max(1, 2);
// max_value is 2
Que font les traits de soulignement à l'intérieur du #define
et comment renvoie-t-il un pointeur de fonction?
gcc -E
) pour voir ce qu'elle fait?Réponses:
En utilisant cette macro,
s'étend à:
Dans les accolades, cela utilise les fonctions imbriquées de GCC pour créer une fonction qui effectue l'opération souhaitée. Dans le cadre interne, il a le nom
_
.Ensuite, comme indiqué par interjay, les expressions de déclaration de GCC sont utilisées. En effet, la fonction
_
est affectée au pointeurmax
.Si une telle macro n'est pas utilisée, cela pourrait être écrit différemment et utilisé comme:
Les trois méthodes peuvent être comparées dans cet exemple de code .
la source
max(4, -30);
place deapply_binary_op(max, 4, -30);
?Cela s'appelle une expression de déclaration et crée une "lambda" (ou fonction imbriquée ) et lui renvoie un pointeur. Il est spécifique à GNU C.
La macro se développe pour:
Le
_
à la fin est comme unreturn
.Le trait de soulignement est en fait le nom de la fonction qui est créée et "renvoyée". Il est utilisé parce que c'est un identifiant peu utilisé (pour une bonne raison;
_
c'est probablement l'identifiant le moins descriptif possible).La raison pour laquelle l'expression d'instruction est utilisée
_
ne le sera donc pas après la fin de la portée de l'expression d'instruction.Donc, en passant par la macro:
ret_type
est le type de retour de la "lambda"._
est le nom de la fonction utilisée à l'intérieur, car il s'agit d'un nom d'identifiant peu commun._body
se compose des arguments et du corps de la fonction. Le dernier_
"renvoie" le "lambda".Ce code se trouve sur Let's Destroy C (qui est un nom approprié). Vous ne devriez pas l'utiliser. Il fera fonctionner votre code uniquement sur les compilateurs qui prennent en charge les extensions GNU C. Au lieu de cela, écrivez simplement une fonction ou une macro.
Si vous utilisez beaucoup de constructions comme celle-ci ou si vous voulez plus de fonctionnalités, je vous suggère d'utiliser C ++. Avec C ++, vous pouvez faire quelque chose de similaire et avoir du code portable.
la source