web-dev-qa-db-fra.com

Comment vérifier la taille d'une structure au moment de la compilation?

Je souhaite ajouter du code qui, lors de la compilation, vérifie la taille d'une structure pour s'assurer qu'il s'agit d'une taille prédéfinie. Par exemple, je veux m'assurer que la taille de cette structure est de 1024 octets lorsque je porte ce code ou lorsque j'ajoute/supprime des éléments de la structure pendant la compilation:

#pack(1)
struct mystruct
{
    int item1;
    int item2[100];
    char item3[4];
    char item5;
    char padding[615];
 }

Je sais comment faire cela pendant l'exécution en utilisant un code tel que celui-ci:

 if(sizeof(mystruct) != 1024)
 { 
     throw exception("Size is not correct");
 }

Mais c'est un gaspillage de traitement si je le fais pendant le temps d'exécution. Je dois faire cela pendant le temps de compilation.

Comment puis-je faire cela pendant la compilation?

32
mans

Vous pouvez vérifier la taille lors de la compilation:

static_assert (sizeof(mystruct) == 1024, "Size is not correct");

Vous avez besoin de C++ 11 pour cela. Boost propose une solution de contournement pour les compilateurs pré-c ++ 11:

BOOST_STATIC_ASSERT_MSG(sizeof(mystruct) == 1024, "Size is not correct");

Voir la documentation .

34
n.m.

Si vous n'avez ni C++ 11 ni Boost, vous pouvez essayer ceci:

typedef char assertion_on_mystruct[(   sizeof(mystruct)==1024   )*2-1 ];

Si l'instruction est fausse, alors ce typedefs un type de tableau avec une taille négative, et votre compilateur devrait donner un message d'erreur. Si true, la taille sera un, une taille valide. Par exemple, g ++ donne:

template.cpp:10:70: error: size of array ‘assertion_on_mystruct’ is negative

J'admets que ce n'est pas la chose la plus utile, car elle ne vous indique que le numéro de ligne de l'erreur. Mais c’est la technique la plus simple, autonome, à laquelle je puisse penser.

Une macro plus générale est:

#define DUMB_STATIC_ASSERT(test) typedef char assertion_on_mystruct[( !!(test) )*2-1 ]

DUMB_STATIC_ASSERT( sizeof(mystruct)==1024 );
DUMB_STATIC_ASSERT( sizeof(my_other_struct)==23 );
DUMB_STATIC_ASSERT( sizeof(minimum_size_struct) >= 23 );
19
Aaron McDaid

Depuis C++ 11, vous avez static_assert qui est traité lors de la compilation:

static_assert(sizeof(mystruct) == 1024, "Size is not correct");

Si la taille n'est pas 1024 octets, vous obtiendrez une erreur de compilation.

6

Si vous voulez le vérifier au compilation, vous pouvez utiliser la phase de métaprogrammation du modèle.

En C++ standard, vous avez le paramètre static assert de boost, masqué par une macro BOOST_STATIC_ASSERT..__ que vous utiliseriez de la manière suivante:

#include <boost/static_assert.hpp>
...
BOOST_STATIC_ASSERT(sizeof(mystruct) == 1024);

La compilation du code ci-dessus échouera si l'assertion n'est pas remplie, avec un message d'erreur semi-lisible.

En C++ 11, vous obtenez une fonctionnalité plus simple avec static assertions qui introduit un nouveau mot clé static_assert.

static_assert(sizeof(mystruct) == 1024,"Size is not correct");

Il est impossible de faire la même chose à la phase préprocesseur mais cela ne semble pas vraiment être nécessaire dans votre cas.

4
CygnusX1

Veuillez noter que le rembourrage est inclus dans sizeof ():

struct A { int i; bool b; };

typedef char assertion_on_A[( ((sizeof(A)))== 8 )*2-1 ];
static_assert(sizeof(A) == 8, "sizeof A");

Le typedef et le static_assert s'attendent à la taille 8 ici.

0
karsten