Alors pourquoi les gens utilisent-ils la version (1 << 7) ?
Il s'agit d'une forme de documentation, ce n'est pas un chiffre magique mais 2^7
( deux à la septième puissance ) qui est significatif pour celui qui a écrit le code. Un compilateur optimisant moderne devrait générer exactement le même code pour les deux exemples. Il n'y a donc aucun coût à utiliser cette forme et l'avantage est d'ajouter un contexte.
Utilisation de godbolt nous pouvons vérifier que c'est effectivement le cas, au moins pour plusieurs versions de gcc
, clang
et icc
. En utilisant un exemple simple avec des effets secondaires pour s'assurer que le code n'est pas totalement optimisé :
#include <stdio.h>
void forLoopShift()
{
for(int i = 0; i < (1 << 7); i++)
{
printf("%d ", i ) ;
}
}
void forLoopNoShift()
{
for(int i = 0; i < 128; i++)
{
printf("%d ", i ) ;
}
}
Pour la partie pertinente du code, nous pouvons voir qu'ils génèrent tous les deux ce qui suit voir en direct :
cmpl $128, %ebx
Ce que nous avons, c'est un expression constante entière tel que défini dans la section du projet de norme C11 6.6
Expressions constantes qui dit :
Une constante entière expression117) doit être de type entier et ne doit avoir que des opérandes qui sont des constantes entières, des constantes d'énumération, des constantes de caractères, des expressions sizeof des expressions dont les résultats sont des constantes entières, [...]
et :
Les expressions constantes ne doivent pas contenir d'opérateurs d'affectation, d'incrémentation, de décrémentation, d'appel de fonction, ou des opérateurs de virgule, sauf lorsqu'ils sont contenus dans une sous-expression qui n'est pas évaluée.115)
et nous pouvons voir qu'une expression constante est autorisée à être évaluée pendant la traduction :
Une expression constante peut être évaluée pendant la traduction plutôt que pendant l'exécution, et peut donc être utilisée à n'importe quel endroit où une constante peut se trouver.