Qu'est-ce qu'une macro C / C ++ commune pour déterminer la taille d'un membre de structure?

StackOverflow https://stackoverflow.com/questions/1400660

  •  05-07-2019
  •  | 
  •  

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!

Était-ce utile?

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);  
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top