是否可以在编译时打印出C ++类的大小?

时间:2010-01-05 19:03:31

标签: c++

是否可以在编译时确定C ++类的大小?

我似乎记得模板元编程方法,但我可能会弄错......


抱歉不清楚 - 我希望在构建输出窗口中打印大小

11 个答案:

答案 0 :(得分:125)

如果您确实需要在编译器输出中获取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

答案 1 :(得分:13)

要回答更新的问题 - 这可能有点过分,但它会在编译时打印出类的大小。 Visual C ++编译器中有一个未记录的命令行开关,它将显示类的完整布局,包括它们的大小:

  

该开关是/ d1reportSingleClassLayoutXXX,其中XXX对类名执行子串匹配。

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

答案 2 :(得分:5)

sizeof怎么了?这应该适用于对象和类。

void foo( bar* b )
{
  int i = sizeof bar;
  int j = sizeof *b;

  // please remember, that not always i==j !!!
}

编辑:

这是我想到的例子,但由于某种原因它不起作用。谁能告诉我什么是错的?

#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

答案 3 :(得分:5)

更简单的代码的另一个技巧:

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

------ Build build:项目:cpptest,配置:调试Win32 ------&gt; cpptest.cpp c:\ work \ cpptest \ cpptest \ cpptest.cpp(33):错误C2196:案例值'4'已使用

     

==========构建:0成功,1失败,0最新,0跳过==========

编辑: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;
}
  

------ Build build:Project:cpptest,Configuration:Debug Win32 ------ cpptest.cpp c:\ work \ cpptest \ cpptest \ cpptest.cpp(29):error C2196:case value '48'已经使用==========构建:0成功,1   失败,0最新,0跳过==========

答案 4 :(得分:4)

sizeof()确定编译时的大小。

它在编译时才起作用,因此你不能将它与预处理器一起使用。

答案 5 :(得分:1)

这是一个产生警告而不是错误的版本:

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

看到它正在运行here。顺便说一下,你可以在那里读出大小(48):

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

答案 6 :(得分:0)

有操作符sizeof( int )sizeof( char )所以我认为它可能并且调用可能看起来像sizeof( MyClass )

答案 7 :(得分:0)

然而,另一个技巧导致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&gt; ------ Build build:Project:cpptest,Configuration:Release Win32   ------ 1&gt; cpptest.cpp 1&gt; cpptest.cpp(14):错误C2664:'proc1':无法将参数1从'int [48]'转换为'void * []'1&gt;
  指向的类型是无关的;转换需要reinterpret_cast,   C风格的演员表或功能风格的演员表   ==========构建:0成功,1个失败,0个最新,0个跳过==========

因此sizeof(struct X)为48.这也适用于C代码。

答案 8 :(得分:0)

这是我使用的片段:

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

答案 9 :(得分:0)

此宏基于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;

还有一些解决方法,但很容易使用。

答案 10 :(得分:0)

我开发了一个名为编译时打印机的工具,用于在编译期间输出值和类型。

您可以通过以下方式在线试用:https://viatorus.github.io/compile-time-printer/

可以在此处找到存储库:https://github.com/Viatorus/compile-time-printer

要获取任何类型的大小作为输出:

constexpr auto unused = ctp::print(sizeof(YourType));