J'écris une application en C (GCC) qui fait beaucoup de comparaison de chaînes. Toujours une chaîne inconnue / dynamique avec une longue liste de chaînes constantes de compilation. Donc je pensais que je hachai la chaîne dynamique et comparez le hachage résultant avec des hachages précumutées des chaînes constantes.
Le fait que cela j'ai le hachage-algorithme dans une fonction (pour les chaînes dynamiques d'exécution) et comme macro. GCC évalue le hachage pendant la compilée. p>
J'ai eu ceci: p> maintenant à la question suivante: p> est-ce possible Pour créer une macro qui se développe à hay_calcx (s) où X est la longueur de la chaîne constante passée à la macro? p> J'ai essayé mais cela ne fonctionne pas. < / p> merci! p> p>
3 Réponses :
Vous pouvez utiliser l'opérateur ternaire:
#define ASSERT_zero(e) (!sizeof(struct{int:!!(e);})) #define HASH_CALCX(s) (ASSERT_zero(strlen(s) <= 5) + \ (strlen(s) == 5 ? HASH_CALC5(s) : \ etc
Je peux confirmer que cela fonctionne -> Produit une constante de temps de compilation. Donc, c'est une solution de contournement valide que je pourrais utiliser si aucune meilleure réponse (solution) n'est donnée ... merci jusqu'à présent! (Je n'aime même pas même les trucs hash_calc1 / hash_calc2 / hash_calc3. De cette façon, j'aurais une macro de monstre de plus)
Malheureusement, en C, la décomposition de chaîne n'est pas une expression constante. Ce qui suit n'est pas valide:
switch (x) { case HASH_CALC('f', 'o', 'o'): ... case HASH_CALC('f', 'o', 'o', 'b', 'a', 'r'): ... }
J'aime votre réponse comme si vous avez dit que vos macros peuvent également être utilisées dans une déclaration de commutation. Vous avez juste une question difficile: pourquoi le (x + 0) dans la macro au lieu de juste x?
@xatian: C'est un tour. Il y a 64 macros consommant au plus 64 arguments. Cependant, s'il y a moins d'arguments, les macros restantes obtiennent une chaîne vide en tant que paramètre. Donc x code> peut être vide et donnerait une erreur de syntaxe car l'expression serait
(== 0? ...) code> avec +0, cela donne
((( +0) == 0? ...) code>. Ce n'est pas 100% propre :). Cela me fait penser que vous n'avez peut-être pas besoin d'entrer dans la trailing 0 dans les paramètres HASH_CALC.
Eh bien ... J'ai testé un peu et il semble que vos miroirs miroirs la corde passée à elle -> Le hachage résultant est faux. Après avoir pensé que ça a du sens :-)
Bien que ce soit incroyable de ce qu'il est possible de faire avec les macros, c'est que le moyen le meilleur / le plus maintenu de le faire? P>
Je serais enclin à placer les chaînes dans un autre fichier et à utiliser un script Perl pour générer les haubans et sortie un fichier source C ++ contenant les chaînes et les hachages dans une structure de données pratique. P>
Votre maquette pourrait être configuré pour revenir sur le script Perl lorsque les chaînes sont modifiées. P>
Pas nécessaire.
Strlen Code> fonctionne parfaitement pour les constantes de cordes, retourner une constante de compilétime.
@Damon bien ... #define hash_calcx (s) (Hash_Merge2 (Hash_Calc, SHLEN (s)) (s) (s) (s) (s) (s) (s), soit comme la Strlen ("") n'est pas étendue.
Comment
hash_calc_start code> défini?
#define hash_calc_start 0 code>?
En fait, il est statique const non signé long hash_calc_start = 5381; Mais ce n'est pas un problème de le définir comme macro-constante si cela aide mon problème :-)
Avez-vous eu envie de simplement appeler votre fonction Hash au lieu d'utiliser une macro? Si la définition de la fonction est dans la même unité de traduction, tout compilateur moderne doit être capable de l'aligner et de réduire éventuellement une constante.
C'est le problème ---> GCC fait en ligne la fonction au lieu de simplement mettre la constante résultante là-bas.