Comment puis-je utiliser “sizeof” dans une macro préprocesseur?
Est-il possible d'utiliser un sizeof
dans une macro préprocesseur?
Par exemple, il y a eu une tonne de situations au cours des années où j'ai voulu faire quelque chose comme:
#if sizeof(someThing) != PAGE_SIZE
#error Data structure doesn't match page size
#endif
La chose exacte que je suis ici de vérification est complètement constitué le point est, j'ai souvent envie de mettre dans ces types de (de la taille ou de l'alignement) des contrôles de compilation afin de se prémunir contre quelqu'un de la modification d'une structure de données qui pourrait perdre l'alignement ou re-taille, les choses qui serait casser.
Inutile de dire que je ne semble pas être en mesure d'utiliser un sizeof
de la manière décrite ci-dessus.
- C'est la raison exacte de construire des systèmes existent.
- C'est la raison exacte #erreur directives devraient toujours être entre guillemets doubles (indéterminé de caractères constante en raison de "ne pas").
Vous devez vous connecter pour publier un commentaire.
Pas. Les directives conditionnelles prendre un ensemble restreint d'expressions conditionnelles;
sizeof
est l'une des choses à ne pas autorisées.Prétraitement directives sont évaluées avant que la source est analysé (au moins conceptuellement), donc il n'y a pas tout les types des variables ou encore pour obtenir leur taille.
Cependant, il existe des techniques pour arriver au moment de la compilation des assertions dans C (voir, par exemple,cette page).
Il y a plusieurs façons de le faire.
Extraits suivants ne produisent pas de code si
sizeof(someThing)
est égal àPAGE_SIZE
; sinon, ils vont produire une erreur de compilation.1. C11 façon
De départ avec C11 vous pouvez utiliser
static_assert
(nécessite#include <assert.h>
).Utilisation:
2. Macro personnalisée
Si vous voulez juste pour obtenir une erreur de compilation lors de la
sizeof(something)
n'est pas ce que vous attendez, vous pouvez utiliser la macro suivante:Utilisation:
Cet article explique en détails pourquoi il fonctionne.
3. MS-spécifique
Sur le compilateur C++ de Microsoft, vous pouvez utiliser C_ASSERT macro (nécessite
#include <windows.h>
), qui utilise un truc similaire à celle décrite dans la section 2.Utilisation:
gcc
(testé en version 4.8.4) (Linux). Au((void)sizeof(...
il des erreurs avecexpected identifier or '(' before 'void'
etexpected ')' before 'sizeof'
. Mais, en principe,size_t x = (sizeof(...
au lieu de cela ne fonctionne pas comme prévu. Vous avez à "utiliser" le résultat, en quelque sorte. Pour le permettre d'être appelé plusieurs fois soit à l'intérieur d'une fonction ou à la portée globale, quelque chose commeextern char _BUILD_BUG_ON_ [ (sizeof(...) ];
peut être utilisé à plusieurs reprises (pas d'effets secondaires, ne sont pas réellement de référence_BUILD_BUG_ON_
n'importe où).Je sais que ce fil est vraiment vieux, mais...
Ma solution:
Aussi longtemps que cette expression équivaut à zéro, il compile bien. Rien d'autre, et il explose là. Parce que la variable est extern avais (il ne prend pas de place, et aussi longtemps que personne n'y fait référence (ce qui ne va pas) il ne sera pas provoquer une erreur de lien.
Pas aussi souple comme l'affirment macro, mais je n'arrivais pas à compiler dans ma version de GCC et ce sera... et je pense que ça va compiler juste au sujet de n'importe où.
Je sais que c'est une réponse tardive, mais d'ajouter à Mike version, voici une version qui n'a pas d'allouer de la mémoire. Je ne suis pas venu jusqu'à la taille originale de vérifier, je l'ai trouvé sur internet il y a des années et, malheureusement, ne peut pas référence à l'auteur. Les deux autres sont juste des extensions de la même idée.
Parce qu'ils sont typedef est, rien n'est alloué. Avec l' _LIGNE ___ dans le nom, c'est toujours un nom différent, de sorte qu'il peut être copié et collé en cas de besoin. Cela fonctionne sous MS Visual Studio C compilateurs, et GCC Bras de compilateurs. Il ne fonctionne pas dans CodeWarrior, CW se plaint de redéfinition, ne faisant pas usage de l' _LIGNE ___ préprocesseur construire.
#define STATIC_ASSERT(condition) typedef char p__LINE__[ (condition) ? 1 : -1];
Qu'en macro suivante:
Par exemple dans le commentaire MSVC dit quelque chose comme:
#if
directive de préprocesseur.L'existant réponses juste montrer comment faire pour obtenir l'effet de la "compilation des affirmations en fonction de la taille d'un type. Qui peut répondre à l'OP, dans ce cas particulier, mais il existe d'autres cas où vous avez vraiment besoin d'un préprocesseur conditionnelle basée sur la taille du type. Voici comment le faire:
Écrire vous-même un petit programme C comme:
Compiler que. Écrire un script dans votre langage de script favori, qui exécute le programme C ci-dessus et obtient sa sortie. Utilisez cette sortie pour générer un fichier en-tête C. Par exemple, si vous étiez à l'aide de Ruby, il pourrait ressembler à:
Puis ajouter une règle à votre Makefile ou un autre script de construction, ce qui va la faire exécuter le script ci-dessus pour construire
sizes.h
.Inclure
sizes.h
partout où vous avez besoin d'utiliser le préprocesseur conditionnelles basées sur les tailles.Fait!
(Avez-vous déjà tapé
./configure && make
de bâtir un programme? Ceconfigure
scripts n'est fondamentalement juste comme ci-dessus...)Tout comme une référence à cette discussion, je signale que certains compilateurs obtenir sizeof() ar pré-processeur de temps.
JamesMcNellis réponse est correcte, mais certains compilateurs passer par cette limitation (ce qui viole probablement strictes de la norme ansi c).
Comme un cas de cela, je me réfère à l'IAR C-compiler (sans doute le meilleur l'un pour les professionnels de la microcontrôleur/programmation embarquée).
sizeof
au temps de prétraitement.sizeof
doit être traité simplement comme un identifiant.#if (sizeof(int) == 8)
réellement effectuées (sur certains compilateurs)." La réponse: "Doit avoir été avant mon temps.", a partir de Dennis Ritchie.#define SIZEOF(x) ((char*)(&(x) + 1) - (char*)&(x))
pourrait fonctionner#define SIZEOF_TYPE(x) (((x*)0) + 1)
#if
condition. Il ne fournit aucune prestation sursizeof(x)
.Dans mon portable code c++ ( http://www.starmessagesoftware.com/cpcclibrary/ ) a voulu mettre un coffre-fort de la garde de la taille de certains de mes structures ou classes.
Au lieu de trouver un moyen pour le préprocesseur pour lancer un message d'erreur ( qui ne peut pas travailler avec sizeof() comme il est dit ici ), j'ai trouvé une solution ici que le compilateur renvoie une erreur.
http://www.barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99
J'ai dû adapter ce code pour faire lever une erreur dans mon compilateur (xcode):
En C11
_Static_assert
mot-clé est ajouté. Il peut être utilisé comme:La
sizeof
opérateur n'est pas disponible pour le préprocesseur, mais vous pouvez transférer dessizeof
pour le compilateur et de vérifier l'état de l'exécution:compiler_size
servir? Quel est votre exemple essayer de montrer?