12
votes

Comment mettre en œuvre une macro générique en C?

FUNC(param);
When param is char *,dispatch to func_string.when it's int,dispatch to func_intI think there may be a solution to this,as variable types are known at compile time..

1 commentaires

Même si cela était possible, ce serait Fugchy. C n'a pas été conçu pour cela. Utilisez des structures et des syndicats, vous pouvez même obtenir une expédition de temps d'exécution de cette façon.


6 Réponses :


11
votes

Les types de variables sont connus du compilateur, mais pas au préprocesseur (qui voit simplement le code simplement comme texte non structuré un flux de jetons et effectue uniquement des opérations de remplacement simples). Je crains donc de ne pouvoir y parvenir avec C macros.

en C ++, ils ont inventé des modèles pour résoudre ces problèmes (et plus).


1 commentaires

C'est une fausse conclusion. Le préprocesseur n'a pas besoin de connaître des types d'arguments, si vous pouvez organiser une expansion macro, de sorte que le compilateur puisse effectuer l'analyse. Voir ARNAUD576875's Répondre Comment résoudre ce problème pour le compilateur GNU. En outre, le préprocesseur ne voit pas le code sous forme de texte non structuré, mais comme un flux de jeton , qui est une différence importante.



1
votes

Vous ne pouvez pas faire cela avec une macro. La valeur de la macro est substituée au moment de la compilation et n'est pas intégrée. Ils ne sont que des substitutions.


0 commentaires

16
votes

Ceci sera possible avec C1X mais pas dans la norme actuelle.

Ce sera ressemblent à ceci: xxx


1 commentaires

Comme cette question apparaît d'abord sur Google: Ceci est maintenant possible à l'aide de C11 en.cppreference.com / W / C / Langue / Générique



4
votes

Il n'y a aucune possibilité d'exécuter les types de chèques de temps dans C89 / ANSI C, mais il y a une extension à la GCC qui le permet. typeof ou quelque chose le long de ces lignes si je me souviens. Je l'ai vu dans le noyau Linux une fois.

dans Kernel.h : P>

#define min(x, y) ({                \
typeof(x) _min1 = (x);          \
typeof(y) _min2 = (y);          \
(void) (&_min1 == &_min2);      \
_min1 < _min2 ? _min1 : _min2; })


1 commentaires

Ce n'est pas un chèque de type d'exécution - comme C n'est pas dactylographié dynamiquement, tapez les informations sont uniquement disponibles au moment de la compilation.



1
votes

Les types de variables sont en effet connus au moment de la compilation, mais la macro expansion a lieu avant la compilation. Je vous suggère d'implémenter 2 fonctions surchargées au lieu d'une macro.


0 commentaires

6
votes

Vous pouvez tester les caractéristiques des types.

Par exemple, int code> peut contenir une valeur négative, tandis que char * code> ne peut pas. Donc, si ((typeof (param)) - 1) , param code> est non signé: p> xxx pre>

le compilateur Évidemment optimise cela. P>

Essayez ici: http://ideone.com/et0v1 P>

Ce serait encore plus facile si les types avaient des tailles différentes. Par exemple, si vous souhaitez écrire une macro générique que de gérer différentes tailles de caractères: p> xxx pré>


gcc a un __ intégré_types_compatible_p () code> fonction intégrée pouvant vérifier la compatibilité des types:

#define FUNC(param)                                                        \ 
    __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), int) \ 
        , func_int(param)                                                  \ 
        , __builtin_choose_expr(__builtin_types_compatible_p(typeof(param), char*) \ 
            , func_string(param)                                           \ 
            , /* The void expression results in a compile-time error       \ 
                 when assigning the result to something.  */               \ 
            ((void)0)                                                      \ 
        )                                                                  \ 
    )


4 commentaires

func_int (x); , func_string (x); et mettez le tout à l'intérieur d'un do {} tandis que (0)


J'avais à l'origine joint le code dans do {} alors que () parce que ce n'était pas une macro ;-)


-1 typeof n'est pas c mais aussi une extension GCC. Qu'est-ce qui vous fait penser qu'une adresse ne peut pas avoir le «signe».


((char *) -1) <0 est toujours faux si le type de pointeur est non signé. (En supposant que les pointeurs ne soient pas signés, n'est-ce pas?)