IT Share you

컴파일 타임에 C ++ 클래스의 크기를 인쇄 할 수 있습니까?

shareyou 2020. 11. 29. 12:37
반응형

컴파일 타임에 C ++ 클래스의 크기를 인쇄 할 수 있습니까?


컴파일 타임에 C ++ 클래스의 크기를 결정할 수 있습니까?

템플릿 메타 프로그래밍 방법을 기억하는 것 같지만 착각 할 수 있습니다.


명확하지 않아 죄송합니다-빌드 출력 창에 크기를 인쇄하고 싶습니다.


컴파일러 출력에서 ​​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는 클래스 이름에 대해 하위 문자열 일치를 수행합니다.

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


더 간단한 코드를 사용하는 또 다른 트릭 :

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

------ 빌드 시작 : 프로젝트 : cpptest, 구성 : Win32 디버그 ------> 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;
}

------ 빌드 시작 : 프로젝트 : cpptest, 구성 : Win32 디버그 ------ cpptest.cpp c : \ work \ cpptest \ cpptest \ cpptest.cpp (29) : 오류 C2196 : 케이스 값 '48' 이미 사용됨 ========== 빌드 : 0 성공, 1 실패, 0 최신 상태, 0 건너 뛰기 ==========


sizeof ()는 컴파일 타임에 크기를 결정합니다.

컴파일 할 때까지 작동하지 않으므로 전처리 기와 함께 사용할 수 없습니다.


뭐가 잘못 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

다음은 오류가 아닌 경고를 생성하는 버전입니다.

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

여전히 약간의 해결 방법이지만 사용하기 쉽습니다.


There is operator sizeof( int ), sizeof( char ) so I think that it is possible and call probably look like sizeof( MyClass )


Yet, another trick causing the VC++2010 compiler to complain about incorrect use of compile time integer:

// 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: Project: cpptest, Configuration: Release Win32 ------ 1> cpptest.cpp 1>cpptest.cpp(14): error C2664: 'proc1' : cannot convert parameter 1 from 'int [48]' to 'void *[]' 1>
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Hence sizeof (struct X) is 48. This also works for C code.


This is the snippet, that I use:

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

To get the size, instantiate the function anywhere in the code, for example, within a statement:

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

The error will look like:

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

참고URL : https://stackoverflow.com/questions/2008398/is-it-possible-to-print-out-the-size-of-a-c-class-at-compile-time

반응형