Qu'est-ce qu'une macro C / C ++ commune pour déterminer la taille d'un membre de structure?
Question
En C / C ++, comment puis-je déterminer la taille de la variable membre d'une structure sans avoir à définir une variable factice de ce type de structure? Voici un exemple de la façon de faire les choses mal, mais montre l’intention:
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const size_t sizeof_MyStruct_x = sizeof(myStruct_t.x); // error
Pour référence, voici comment trouver la taille de 'x' si vous définissez d'abord une variable factice:
myStruct_t dummyStructVar;
const size_t sizeof_MyStruct_x = sizeof(dummyStructVar.x);
Cependant, j'espère éviter de créer une variable factice uniquement pour obtenir la taille de 'x'. Je pense qu'il existe un moyen intelligent de reformuler 0 en tant que myStruct_t pour aider à trouver la taille de la variable de membre 'x', mais cela fait assez longtemps que j'ai oublié les détails et je ne peux pas sembler obtenir une bonne recherche Google à ce sujet. . Le savez-vous?
Merci!
La solution
En C ++ (selon ce que disent les balises), votre "variable factice" " le code peut être remplacé par:
sizeof myStruct_t().x;
Aucun objet myStruct_t ne sera créé: le compilateur ne calcule que le type statique de l'opérande sizeof, il n'exécute pas l'expression.
Cela fonctionne en C, et en C ++, c'est mieux car cela fonctionne aussi pour les classes sans constructeur no-args accessible:
sizeof ((myStruct_t *)0)->x
Autres conseils
J'utilise la macro suivante:
#include <iostream>
#define DIM_FIELD(struct_type, field) (sizeof( ((struct_type*)0)->field ))
int main()
{
struct ABC
{
int a;
char b;
double c;
};
std::cout << "ABC::a=" << DIM_FIELD(ABC, a)
<< " ABC::c=" << DIM_FIELD(ABC, c) << std::endl;
return 0;
}
Trick traite 0 comme un pointeur sur votre structure. Ceci est résolu à la compilation, donc c'est sûr.
Vous pouvez facilement faire
sizeof(myStruct().x)
Le paramètre sizeof n'étant jamais exécuté, vous ne créerez pas vraiment cet objet.
N'importe lequel d'entre eux devrait fonctionner:
sizeof(myStruct_t().x;);
ou
myStruct_t *tempPtr = NULL;
sizeof(tempPtr->x)
ou
sizeof(((myStruct_t *)NULL)->x);
Etant donné que sizeof
est évalué au moment de la compilation, et non à l'exécution, vous n'aurez pas de problème pour déréférencer un pointeur NULL.
En C ++ 11, cela peut être fait avec sizeof (myStruct_t :: x)
. C ++ 11 ajoute également std :: declval , qui peut être utilisé à cette fin. (entre autres):
#include <utility>
typedef struct myStruct {
int x[10];
int y;
} myStruct_t;
const std::size_t sizeof_MyStruct_x_normal = sizeof(myStruct_t::x);
const std::size_t sizeof_MyStruct_x_declval = sizeof(std::declval<myStruct_t>().x);
À partir de l'en-tête de mes macros utilitaires:
#define FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
appelé comme suit:
FIELD_SIZE(myStruct_t, x);