Est-il possible d’imprimer la taille d’une classe C ++ au moment de la compilation?

Est-il possible de déterminer la taille d’une classe C ++ au moment de la compilation?

Je me souviens d’une méthode de méta-programmation modèle, mais je peux me tromper …


désolé de ne pas être plus clair – je veux que la taille soit imprimée dans la fenêtre de sortie de compilation

Si vous avez vraiment besoin d’obtenir sizeof (X) dans la sortie du compilateur, vous pouvez l’utiliser comme paramètre pour un type de modèle incomplet:

template struct Wow; struct foo { int a,b; }; Wow wow; $ g++ -c test.cpp test.cpp:5: error: aggregate 'Wow<8> wow' has incomplete type and cannot be defined 

Pour répondre à la question mise à jour – cela peut être excessif, mais cela imprimera les tailles de vos classes au moment de la compilation. Il existe un commutateur de ligne de commande non documenté dans le compilateur Visual C ++ qui affiche les dispositions complètes des classes, y compris leurs tailles:

Ce commutateur est / d1reportSingleClassLayoutXXX, où XXX effectue des correspondances de sous-chaînes avec le nom de la classe.

http://blogs.msdn.com/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022.aspx

Quel est le problème avec sizeof ? Cela devrait fonctionner sur les objects et les classes.

 void foo( bar* b ) { int i = sizeof bar; int j = sizeof *b; // please remember, that not always i==j !!! } 

Modifier:

C’est l’exemple auquel je pensais, mais pour une raison quelconque, cela ne fonctionne pas. Quelqu’un peut-il me dire ce qui ne va pas?

 #include  using namespace std; class bar { public: int i; bar( int ii ) { i = ii; } virtual ~bar(){ i = 0; } virtual void d() = 0; }; class bar2: public bar { public: long long j; bar2( int ii, long long jj ):bar(ii){ j=jj; } ~bar2() { j = 0; } virtual void d() { cout << "virtual" << endl; }; }; void foo( bar *b ) { int i = sizeof (bar); int j = sizeof *b; cout << "Size of bar = " << i << endl; cout << "Size of *b = " << j << endl; b->d(); } int main( int arcc, char *argv[] ) { bar2 *b = new bar2( 100, 200 ); foo( b ); delete b; return 0; } 

L’application a été exécutée sur Linux (gcc 4.4.2):

 [elcuco@pinky ~/tmp] ./sizeof_test Size of bar = 8 Size of *b = 8 virtual 

sizeof () détermine la taille au moment de la compilation.

Il ne fonctionne pas avant la compilation, vous ne pouvez donc pas l’utiliser avec le préprocesseur.

Un autre truc avec un code plus simple:

 int dummy; switch (dummy) { case sizeof(dummy): case sizeof(dummy): break; } 

—— Build started: Projet: cpptest, Configuration: Debug Win32 ——> cpptest.cpp c: \ work \ cpptest \ cpptest \ cpptest.cpp (33): erreur C2196: valeur de cas ‘4 ‘ déjà utilisé

========== Build: 0 réussi, 1 échoué, 0 mis à jour, 0 ignoré ==========

EDIT: dummy ci-dessus est une variable intégrale pour la condition du commutateur afin de satisfaire la syntaxe requirejse. Utilisez sizeof(X) pour la constante de casse:

Cela fonctionne aussi pour le code C.

 struct X { int a,b; int c[10]; }; int _tmain(int argc, _TCHAR* argv[]) { int dummy; switch (dummy) { case sizeof(X): case sizeof(X): break; } return 0; } 

—— Build started: Projet: cpptest, Configuration: Debug Win32 —— cpptest.cpp c: \ work \ cpptest \ cpptest \ cpptest.cpp (29): erreur C2196: valeur de casse ’48’ déjà utilisé ========== Build: 0 réussi, 1 échoué, 0 mis à jour, 0 sauté ==========

Voici une version qui produit un avertissement plutôt qu’une erreur:

  /** Comstack-time sizeof as a warning so compilation can continue */ struct TestStruct { int i1; float f1; const char* pchar1; double d1; char c1; void* pv1; bool b1; }; template struct PrintNum { enum { value = n }; }; template struct _{ operator char() { return number + 256; } }; #define PRINT_AS_WARNING(constant) char(_()) int main() { PRINT_AS_WARNING(PrintNum::value); return 0; } 

Voyez-le courir ici . En passant, vous pouvez lire la taille ( 48 ) dès la sortie de l’assemblage:

 leaq -1(%rbp), %rax movq %rax, %rdi call _<48>::operator char() movl $0, %eax leave ret 

Il y a operator sizeof( int ) , sizeof( char ) donc je pense que c’est possible et que l’appel ressemble probablement à sizeof( MyClass )

Pourtant, une autre astuce amène le compilateur VC ++ 2010 à se plaindre d’une utilisation incorrecte de l’entier de compilation:

 // cpptest.cpp : Defines the entry point for the console application. // #include "stdafx.h" struct X { int a[11]; char c[2]; }; void proc1(void* s[1]) { } int _tmain(int argc, _TCHAR* argv[]) { int b[sizeof(X)]; proc1(b); return 0; } 

1> —— Build started: Projet: cpptest, Configuration: Release Win32 —— 1> cpptest.cpp 1> cpptest.cpp (14): erreur C2664: ‘proc1’: impossible de convertir le paramètre 1 de ‘int [48]’ à ‘void * []’ 1>
Les types pointés ne sont pas liés; la conversion nécessite reinterpret_cast, cast C-style ou cast de style fonction ========== Build: 0 réussi, 1 échoué, 0 mis à jour, 0 sauté ==========

Par conséquent, sizeof (struct X) est 48. Cela fonctionne également pour le code C.

Ceci est l’extrait, que j’utilise:

 template  void get_sizeof() { switch (*((int*)0x1234)) { case sizeof(T): case sizeof(T):; } } 

Pour obtenir la taille, instanciez la fonction n’importe où dans le code, par exemple dans une instruction:

 struct S { long long int ill; }; get_sizeof; 

L’erreur ressemblera à:

 error: duplicate case value '8' switch (*((int*)0x1234)) { case sizeof(T): case sizeof(T):; } ^ 

Cette macro est basée sur la réponse de grep. Définissez la macro comme ci-dessous:

 #define COMPILE_TIME_SIZEOF(t) template struct SIZEOF_ ## t ## _IS; \ struct foo { \ int a,b; \ }; \ SIZEOF_ ## t ## _IS SIZEOF_ ## t ## _IS; 

Ensuite, utilisez-le comme ceci:

 COMPILE_TIME_SIZEOF(long); 

Et vous obtiendrez une sortie similaire à celle ci-dessous:

 error: 'SIZEOF_long_IS<4> SIZEOF_long_IS' redeclared as different kind of symbol SIZEOF_ ## t ## _IS SIZEOF_ ## t ## _IS; 

Encore un peu de contournement, mais assez facile à utiliser.