Можно ли определить размер класса С++ во время компиляции?
Кажется, я помню метод метапрограмм шаблона, но я мог ошибаться...
извините за неясность - я хочу, чтобы размер был напечатан в окне вывода сборки
Можно ли определить размер класса С++ во время компиляции?
Кажется, я помню метод метапрограмм шаблона, но я мог ошибаться...
извините за неясность - я хочу, чтобы размер был напечатан в окне вывода сборки
Если вам действительно нужно получить 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 выполняет сопоставления подстрок с именем класса.
Другой трюк с более простым кодом:
int dummy;
switch (dummy) {
case sizeof(dummy):
case sizeof(dummy):
break;
}
------ Сборка запущена: Проект: cpptest, Конфигурация: Отладка Win32 ------ > cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp(33): ошибка C2196: case значение '4' уже используется
========== Build: 0 удалось, 1 не удалось, 0 обновлено, 0 пропущено ==========
EDIT: dummy
выше - некоторая интегральная переменная для условия переключения, чтобы удовлетворить требуемый синтаксис. Используйте sizeof(X)
для константы case:
Это тоже работает для кода 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, Конфигурация: Отладка Win32 ------ cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp(29): ошибка C2196: значение case '48' уже используется ========== Build: 0 удалось, 1 не удалось, 0 обновлено, 0 пропущено ==========
Что случилось с 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):
[[email protected] ~/tmp] ./sizeof_test
Size of bar = 8
Size of *b = 8
virtual
sizeof() определяет размер во время компиляции.
Он не работает до момента компиляции, поэтому вы не можете использовать его с препроцессором.
Вот версия, которая выдает предупреждение, а не ошибку:
/** 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 $0, %eax
leave
ret
Этот макрос основан на 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;
Все еще немного обходной путь, но достаточно простой в использовании.
Существует оператор sizeof( int )
, sizeof( char )
, поэтому я думаю, что это возможно, и вызов, вероятно, будет выглядеть как sizeof( MyClass )
Тем не менее, еще один трюк, вызывающий компилятор VС++ 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 > ------ Начало сборки: Project: cpptest, Configuration: Release Win32 ------ 1 > cpptest.cpp 1 > cpptest.cpp(14): ошибка C2664: 'proc1': не может преобразовать параметр 1 из 'int [48]' в 'void * []' 1 >
Указанные типы не имеют отношения; для преобразования требуется reinterpret_cast, Литье в стиле C или стиль в стиле функции ========== Build: 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):; }
^