puis-je compter sur mon compilateur pour optimiser strlen sur const char *?

Dans mon callback d’parsing SAX xml (XCode 4, LLVM), je passe beaucoup d’appels à ce type de code:

static const char* kFoo = "Bar"; void SaxCallBack(char* sax_ssortingng,.....) { if ( strcmp(sax_ssortingng, kFoo, strlen(kFoo) ) == 0) { } } 

Est-il prudent de supposer que strlen (kFoo) est optimisé par le compilateur?

(L’exemple de code Apple avait strlen pré-calculé (kFoo), mais je pense que cela est sujet aux erreurs pour un grand nombre de chaînes constantes.)

Edit: Motivation à l’optimisation: l’parsing de ma carte SVG sur iPod touch 2G prend 5 secondes (!) À l’aide de NSXMLParser. Donc, je veux passer à lib2xml et optimiser les comparaisons de chaînes.

Si par “LLVM” vous voulez dire clang, alors oui, vous pouvez compter sur clang -O pour optimiser la strlen . Voici à quoi ressemble le code de votre fonction:

 _SaxCallBack: Leh_func_begin1: pushq %rbp Ltmp0: movq %rsp, %rbp Ltmp1: leaq L_.str1(%rip), %rsi movl $3, %edx callq _strncmp ... 

J’ai changé le strcmp en strncmp , mais le troisième argument a bien été remplacé par le $3 immédiat.

Notez que gcc 4.2.1 -O3 n’optimise pas cet appel strlen et que vous ne pouvez vous attendre à ce qu’il fonctionne que dans les conditions précises de votre question (en particulier, la chaîne et l’appel à strlen doivent figurer dans le même fichier).

N’écris pas des choses comme:

 static const char* kFoo = "Bar"; 

Vous avez créé une variable nommée kFoo qui pointe vers des données constantes. Le compilateur pourra peut-être détecter que cette variable ne change pas et l’optimiser, mais si ce n’est pas le cas, vous avez gonflé le segment de données de votre programme.

Aussi, n’écris pas des choses comme:

 static const char *const kFoo = "Bar"; 

Votre variable kFoo est maintenant kFoo constante et non modifiable, mais si elle est utilisée dans du code indépendant de la position (bibliothèques partagées, etc.), le contenu variera toujours au moment de l’exécution et appenda donc des coûts de démarrage et de mémoire à votre programme. Au lieu de cela, utilisez:

 static const char kFoo[] = "Bar"; 

ou même:

 #define kFoo "Bar" 

En général, vous ne pouvez pas compter dessus. Cependant, vous pouvez utiliser ‘sizeof’ et l’appliquer à un littéral de chaîne. Bien entendu, cela signifie que vous ne pouvez pas définir “kFoo” comme il avait été défini à l’origine.

Ce qui suit devrait fonctionner sur tous les compilateurs et à tous les niveaux d’optimisation.

 #define kFoo "..." ... strcmp(... sizeof(kFoo)) 

Question de suivi:

Avez-vous testé les éléments suivants?

 static std::ssortingng const kFoo = "BAR"; void SaxCallBack(char* sax_ssortingng,.....) { if ( sax_ssortingng == kFoo) { } } 

La lisibilité est gagnante, mais je n’ai aucune idée du coût de la performance.

Au lieu de cela, si vous devez effectuer votre dépêche par vos propres moyens, j’ai constaté que l’utilisation d’une approche semblable à celle d’une machine à états (avec stack) est beaucoup plus lisible et pourrait également améliorer les performances (au lieu d’avoir un grand nombre de balises allumez, vous n’avez que les tags qui peuvent être rencontrés pour le moment).