Можно ли распечатать размер класса C++ во время компиляции?
можно ли определить размер класса C++ во время компиляции?
кажется, я помню метод метапрограммирования шаблона, но я могу ошибаться...
извините, что не яснее - я хочу, чтобы размер был напечатан в окне вывода сборки
10 ответов:
Если вам действительно нужно получить sizeof (X) в выводе компилятора, вы можете использовать его в качестве параметра для неполного типа шаблона:
template<int s> struct Wow; struct foo { int a,b; }; Wow<sizeof(foo)> wow; $ g++ -c test.cpp test.cpp:5: error: aggregate ‘Wow<8> wow’ has incomplete type and cannot be defined
чтобы ответить на обновленный вопрос - это может быть излишним, но он будет печатать размеры ваших классов во время компиляции. В компиляторе Visual C++ есть недокументированный переключатель командной строки, который будет отображать полные макеты классов, включая их размеры:
этот переключатель является /d1reportSingleClassLayoutXXX, где XXX выполняет подстрочные совпадения с классом имя.
что случилось с
sizeof
? Это должно работать на объектах и классах.void foo( bar* b ) { int i = sizeof bar; int j = sizeof *b; // please remember, that not always i==j !!! }
Edit:
это пример, о котором я думал, но по какой-то причине он не работает. Может кто-нибудь сказать мне, что случилось?
#include <iostream> 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; }
приложение было запущено на linux (gcc 4.4.2):
[elcuco@pinky ~/tmp] ./sizeof_test Size of bar = 8 Size of *b = 8 virtual
оператор sizeof() определяет размер во время компиляции.
Он не работает до времени компиляции, поэтому вы не можете использовать его с препроцессором.
еще один трюк с простым кодом:
int dummy; switch (dummy) { case sizeof(dummy): case sizeof(dummy): break; }
------ сборка начата: проект: cpptest, конфигурация: Debug Win32 ------ >cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp (33): ошибка C2196: значение case '4' уже используется
========== сборка: 0 успешно, 1 не удалось, 0 обновлено, 0 пропущено ==========
EDIT:
dummy
выше приведена некоторая интегральная переменная для условия переключения, чтобы удовлетворить требуемому синтаксису. Использоватьsizeof(X)
для случая постоянной:это работает и для кода 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; }
------ сборка начата: проект: cpptest, конфигурация: Debug Win32 ------ cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp (29): ошибка C2196: значение '48' уже используется ========== сборка: 0 успешно, 1 не удалось, 0 обновлено, 0 пропущено ==========
вот версия, которая выдает предупреждение, а не ошибка:
/** Compile-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<unsigned int n> struct PrintNum { enum { value = n }; }; template<int number> struct _{ operator char() { return number + 256; } }; #define PRINT_AS_WARNING(constant) char(_<constant>()) int main() { PRINT_AS_WARNING(PrintNum<sizeof(TestStruct)>::value); return 0; }
смотрите, как он работает здесь. В стороне, вы можете прочитать размер (
48
) прямо из сборки там:leaq -1(%rbp), %rax movq %rax, %rdi call _<48>::operator char() movl , %eax leave ret
есть оператор
sizeof( int )
,sizeof( char )
Так что я думаю, что это возможно и вызов, вероятно, выглядят какsizeof( MyClass )
еще один трюк, заставляющий компилятор VC++2010 жаловаться на неправильное использование целого числа времени компиляции:
// 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>------ Начало сборки: проект: cpptest, конфигурация: Release Win32 ------ 1> cpptest.cpp 1>cpptest.cpp (14): ошибка C2664: 'proc1': не удается преобразовать параметр 1 из 'int [48]' в 'void *[]' 1>
Типы, на которые указывают, не связаны; преобразование требует reinterpret_cast, C-стиля, литые или функция приведения ========== Сборка: 0 успешно, 1 не удалось, 0 обновлено, 0 пропущено ==========следовательно, sizeof (struct X) равен 48. Это также работает для кода на языке C.
Это фрагмент, который я использую:
template <typename T> void get_sizeof() { switch (*((int*)0x1234)) { case sizeof(T): case sizeof(T):; } }
чтобы получить размер, экземпляр функции в любом месте кода, например, в сообщении:
struct S { long long int ill; }; get_sizeof<S>;
ошибка будет выглядеть так:
error: duplicate case value '8' switch (*((int*)0x1234)) { case sizeof(T): case sizeof(T):; } ^
этот макрос основан на ответе grep. Определить макрос, как показано ниже:
#define COMPILE_TIME_SIZEOF(t) template<int s> struct SIZEOF_ ## t ## _IS; \ struct foo { \ int a,b; \ }; \ SIZEOF_ ## t ## _IS<sizeof(t)> SIZEOF_ ## t ## _IS;
тогда используйте его так:
COMPILE_TIME_SIZEOF(long);
и вы получите результат, подобный приведенному ниже:
error: 'SIZEOF_long_IS<4> SIZEOF_long_IS' redeclared as different kind of symbol SIZEOF_ ## t ## _IS<sizeof(t)> SIZEOF_ ## t ## _IS;
еще немного обходной путь, но достаточно прост в использовании.