Eh bien, je suis assez surpris de voir que les alternatives à cette syntaxe n'ont pas été mentionnés. Une autre commune (mais les plus âgés) mécanisme est d'appeler une fonction qui n'est pas défini et s'appuient sur l'optimiseur de compiler l'appel de la fonction si votre affirmation est correcte.
#define MY_COMPILETIME_ASSERT(test) \
do { \
extern void you_did_something_bad(void); \
if (!(test)) \
you_did_something_bad(void); \
} while (0)
Bien que ce mécanisme fonctionne (aussi longtemps que des optimisations sont activés), il a l'inconvénient de ne pas signaler une erreur jusqu'à ce que vous liez, à laquelle il ne parvient pas à trouver la définition de la fonction you_did_something_bad(). C'est pourquoi les développeurs du noyau de départ à l'aide des figures, comme le négatif de la taille des bits largeur de champ et le négatif de la taille des tableaux (le plus tard de la qui a cessé de casser construit dans GCC 4.4).
Dans la sympathie pour le besoin de la compilation des assertions, GCC 4.3 introduit l' error
de la fonction d'attribut qui permet d'étendre cette ancienne concept, mais de générer une erreur de compilation avec un message de votre choix, ne plus cryptique "négatif de la taille de la matrice de" messages d'erreur!
#define MAKE_SURE_THIS_IS_FIVE(number) \
do { \
extern void this_isnt_five(void) __attribute__((error( \
"I asked for five and you gave me " #number))); \
if ((number) != 5) \
this_isnt_five(); \
} while (0)
En fait, comme de Linux 3.9, nous avons maintenant une macro appelée compiletime_assert
qui utilise cette fonction et la plupart des macros en bug.h
ont été mis à jour en conséquence. Encore, cette macro ne peut pas être utilisé comme un initialiseur. Cependant, l'utilisation par la déclaration des expressions (un autre GCC C-extension), vous pouvez!
#define ANY_NUMBER_BUT_FIVE(number) \
({ \
typeof(number) n = (number); \
extern void this_number_is_five(void) __attribute__(( \
error("I told you not to give me a five!"))); \
if (n == 5) \
this_number_is_five(); \
n; \
})
Cette macro va évaluer le paramètre exactement une fois (dans le cas où il a des effets secondaires) et de créer une erreur de compilation qui dit "je vous ai dit de ne pas me donner un cinq!" si l'expression est évaluée à cinq ou n'est pas une constante de compilation.
Alors pourquoi ne sommes-nous pas à l'aide de ces questions, au lieu de négatif de la taille en bits des champs? Hélas, il existe actuellement de nombreuses restrictions de l'utilisation de la déclaration des expressions, y compris leur utilisation en tant que constante d'initialiseurs (pour enum constantes, bits largeur de champ, etc.) même si la déclaration de l'expression est complètement constante de son auto (c'est à dire, peut être pleinement évalués au moment de la compilation et sinon passe à l' __builtin_constant_p()
test). De plus, ils ne peuvent pas être utilisées en dehors du corps d'une fonction.
Espérons-le, GCC modifiera ces lacunes bientôt et permettre constante de la déclaration des expressions pour être utilisé comme une constante, les initialiseurs. Le défi ici est la spécification de langage de définition de ce qui est juridique, une expression constante. C++11 a ajouté le constexpr de mots clés pour ce genre ou de la chose, mais rien d'équivalent n'existe en C11. Tout en C11 n'a d'obtenir statique affirmations, qui permettra de résoudre en partie ce problème, il l'habitude de résoudre tous ces problèmes. J'espère donc que gcc peut faire une constexpr fonctionnalité disponible comme une extension via-std=gnuc99 & -std=gnuc11 ou quelque chose du genre et permettre son utilisation sur la déclaration des expressions et. al.