Подтвердить что ты не робот

Можно ли распечатать размер класса С++ во время компиляции?

Можно ли определить размер класса С++ во время компиляции?

Кажется, я помню метод метапрограмм шаблона, но я мог ошибаться...


извините за неясность - я хочу, чтобы размер был напечатан в окне вывода сборки

4b9b3361

Ответ 1

Если вам действительно нужно получить 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

Ответ 2

Чтобы ответить на обновленный вопрос - это может быть излишним, но это напечатает размеры ваших классов во время компиляции. В компиляторе Visual C++ есть недокументированный переключатель командной строки, который будет отображать полные макеты классов, включая их размеры:

Этот параметр -/d1reportSingleClassLayoutXXX, где XXX выполняет сопоставления подстрок с именем класса.

https://devblogs.microsoft.com/cppblog/diagnosing-hidden-odr-violations-in-visual-c-and-fixing-lnk2022/

Ответ 3

Другой трюк с более простым кодом:

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 пропущено ==========

Ответ 4

Что случилось с 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

Ответ 5

sizeof() определяет размер во время компиляции.

Он не работает до момента компиляции, поэтому вы не можете использовать его с препроцессором.

Ответ 6

Вот версия, которая выдает предупреждение, а не ошибку:

    /** 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

Ответ 7

Этот макрос основан на 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;

Все еще немного обходной путь, но достаточно простой в использовании.

Ответ 8

Существует оператор sizeof( int ), sizeof( char ), поэтому я думаю, что это возможно, и вызов, вероятно, будет выглядеть как sizeof( MyClass )

Ответ 9

Тем не менее, еще один трюк, вызывающий компилятор 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.

Ответ 10

Это фрагмент, который я использую:

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):; }
                                                ^