programing

컴파일 시 sizeof() 결과를 C로 출력하려면 어떻게 해야 하나요?

coolbiz 2022. 7. 2. 14:09
반응형

컴파일 시 sizeof() 결과를 C로 출력하려면 어떻게 해야 하나요?

컴파일 시 sizeof() 결과를 C로 출력하려면 어떻게 해야 하나요?

현재 저는 정적 아사트(다른 웹 리소스에 기반하여 홈브레이드)를 사용하여 sizeof() 결과를 다양한 상수와 비교하고 있습니다.이게 효과가 있는 동안...우아하거나 빠른 것과는 거리가 멀다.변수/구조의 인스턴스를 생성하여 지도 파일을 참조할 수도 있지만 직접 호출/명령/오퍼레이터보다 덜 우아하고 빠릅니다.게다가 이것은 복수의 크로스 컴파일러를 사용한 임베디드 프로젝트입니다.따라서 샘플 프로그램을 만들어 타깃에 로드한 후 값을 읽어내는 것은 위의 어느 것보다도 더 번거로운 일입니다.

경우 GCC는 '(GCC)'입니다.#warning sizeof(MyStruct)는 경고를 출력하기 전에 sizeof()를 실제로 해석하지 않습니다.

비슷한 기능을 찾기 위해 빈둥거리고 있었는데 우연히 이 기능을 발견했습니다.

컴파일 시에 C++ 클래스의 사이즈를 인쇄할 수 있습니까?

그래서 이런 생각이 떠올랐어요

char (*__kaboom)[sizeof( YourTypeHere )] = 1;

VS2015에서는 다음과 같은 경고가 발생합니다.

warning C4047: 'initializing': 'DWORD (*)[88]' differs in levels of indirection from 'int'

여기서 88은 당신이 찾고 있는 사이즈입니다.

완전 해킹이야, 하지만 효과가 있어아마 2년 정도 늦었을지도 모르지만, 이것이 누군가에게 도움이 되기를 바랍니다.

아직 gcc나 clang을 사용해 본 적은 없지만, 만약 나보다 먼저 도착하지 않으면 동작 여부를 확인해 보겠습니다.

편집: clang 3.6에 대해 개봉 즉시 사용 가능

수 은 GCC를 남용하는 이었다.-Wformat매크로에서 다음과 같은 함수를 정의하도록 합니다.

void kaboom_print( void )
{
    printf( "%d", __kaboom );
}

다음과 같은 경고가 표시됩니다.

...blah blah blah... argument 2 has type 'char (*)[88]'

원래 제안보다 약간 더 역겹지만, gcc를 조금 더 잘 아는 사람이라면 남용에 대한 더 나은 경고를 생각할 수 있을 것이다.

된 ★★case의 에러보고 에 관계없이 모든 C 하는 것을 입니다.constant는 C 컴파일러입니다.Visual C++는 Visual 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 started: Project: cpptest, Configuration: Debug Win32 ------
 cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp(29): error C2196: case value '48' already used
 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

그래서 구조 X의 크기는 48이다.

편집 완료(2020년 6월):"duplicate case value"만 출력하는 gcc 또는 기타 컴파일러의 경우 다음 방법을 사용하여 값을 좁힙니다.

1) 케이스 값 1==2를 추가한다(false를 나타냄).

을 좁힙니다. 예를 2) 행좁좁좁 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 。을 해보겠습니다.sizeof(X)16이

#include <stdio.h>
typedef struct _X {
    int a;
    char b[10];
} X;
int main()
{
    printf("Hello World");

    int dummy=0   ;
    switch (dummy) {
    case  1==2:
    case sizeof( X)>16:
    //case 16:
    break;
    }
    return 0;
}

결과:

main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
     case sizeof( X)>16:
     ^~~~
main.c:13:5: error: previously used here
     case  1==2:

즉, 크기(X) <=16)가 거짓입니다.

3) 있는. 될 거라고 . 16번입니다. sizeof(X)==16중복된 케이스 값에 대해 불만이 없는 경우.그럼 그 표현은 참이군요.

으로 4)를 합니다.case 16검증할 수 있습니다.

#include <stdio.h>
typedef struct _X {
    int a;
    char b[10];
} X;
int main()
{
    printf("Hello World");

    int dummy=0   ;
    switch (dummy) {
   // case  1==2:
    case sizeof( X):
    case 16:
    break;
    }
    return 0;
}

결과

main.c: In function ‘main’:
main.c:15:5: error: duplicate case value
     case 16:
     ^~~~
main.c:14:5: error: previously used here
     case sizeof( X):

(X) 사이즈가 16임을 확인합니다.

또는 gcc가 여러 개의 중복을 보고할 수 있으므로 이 트릭은 1개의 패스로 여러 번 추측할 수 있습니다.

#include <stdio.h>
typedef struct _X {
    int a;
    char b[10];
} X;
int main()
{
    printf("Hello World");

    int dummy=0   ;
    switch (dummy) {
    case  1==2: //represents false
    case 1==1: //represents true
    case sizeof( X)>10:
    case sizeof( X)>12:
    case sizeof( X)>14:
    case sizeof( X)>16:
    case  sizeof( X)==16:
    //case 16:
    break;
    }
    return 0;
}

결과

main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
     case sizeof( X)>10:
     ^~~~
main.c:13:5: error: previously used here
     case 1==1:
     ^~~~
main.c:15:5: error: duplicate case value
     case sizeof( X)>12:
     ^~~~
main.c:13:5: error: previously used here
     case 1==1:
     ^~~~
main.c:16:5: error: duplicate case value
     case sizeof( X)>14:
     ^~~~
main.c:13:5: error: previously used here
     case 1==1:
     ^~~~
main.c:17:5: error: duplicate case value
     case sizeof( X)>16:
     ^~~~
main.c:12:5: error: previously used here
     case  1==2:
     ^~~~
main.c:18:5: error: duplicate case value
     case  sizeof( X)==16:
     ^~~~
main.c:13:5: error: previously used here
     case 1==1:
     ^~~~

하는 것sizeof(X) >이 아닙니다.> 10, > 12, > 14는 16입니다.열여섯 살 == 열여섯 살

다음 방법은 GCC, Clang, MSVC 등에서 동작하며 이전 버전에서도 기능 파라미터가 포인터에서 어레이로 스칼라 타입으로 변환되지 않은 것을 기반으로 합니다.컴파일러는 어레이의 크기를 인쇄하기 때문에 출력에서 값을 얻을 수 있습니다.C 모드와 C++ 모드 모두에서 동작합니다.

「 」를 sizeof(long)(온라인에서 재생):

char checker(int);
char checkSizeOfInt[sizeof(long)]={checker(&checkSizeOfInt)};

관련 출력의 예:

  • GCC 4.4.7

<source>:1: note: expected 'int' but argument is of type 'char (*)[8]'

  • 쨍그랑 3.0.0

<source>:1:6: note: candidate function not viable: no known conversion from 'char (*)[8]' to 'int' for 1st argument;

  • MSVC 19.14

<source>(2): warning C4047: 'function': 'int' differs in levels of indirection from 'char (*)[4]'

빠르고 심플한 솔루션(GCC):

(char[sizeof(long long)])"bla";

되며, 에러 메시지의 크기가 됩니다.long long:

ISO C++ forbids casting to an array type 'char [8]'

또 하나의 방법(실제로 기능하는 방법):

char __foo[sizeof(MyStruct) + 1] = {[sizeof(MyStruct)] = ""};

old'ish gcc 5.x와 연동하여 다음과 같은 오류가 발생합니다.

a.c:8:54: error: initializer element is not computable at load time
a.c:8:54: note: (near initialization for 'a[8]')

p.s. 분명히 이것은 (매우) gcc에 특유합니다.다른 방법들은 모두 나에게 효과가 없었다.

//main.cpp
#include <cstddef>
template <std::size_t x>
struct show_size;

void foo()
{
    show_size<sizeof(my_type)>();//!!please change `my_type` to your expected
}

int main()
{
    return 0;
}

코드를 할 수 전에러를 합니다.이 에러는 이 단계에서 합니다.컴파일 전 단계에서 컴파일러는 에러를 발생시킵니다.sizeof(my_type)이치노 §:

g++ main.cpp

우연히 Bakhazard훌륭한 솔루션과 유사한 솔루션을 발견했는데, 이 솔루션은 훨씬 더 장황한 경고를 생성하므로 유용하다고 생각할 수 있습니다.

char (*__fail)(void)[sizeof(uint64_t)] = 1;

그러면 오류 메시지가 생성됩니다.

Function cannot return array type 'char [8]'

은 최신 의 「」를 해 테스트되었습니다.clang(1).

@jws 좋은 생각이야!Hower, sizeof(xxx)는 상수 표현식입니다(VLA, https://en.cppreference.com/w/c/language/sizeof),은 제외).따라서 연산자 크기는 다음과 같은 경우에 한해 사용할 수 있습니다.

enum e1 {dummy=-1};
enum e1 ev;
switch (ev) {
    case sizeof(myType):;
    break;
    default:;
}

내 GCC에서 작동한다: "..\WinThreads.c:18:9: warning: 대소문자 값 '4'가 열거형 'enum e1' [-Wswitch]에 없습니다.

컴파일 시간은 아니지만 런타임 전이기 때문에 일부 사용자에게도 의미가 있을 수 있습니다.

다음과 같이 배열을 정의할 수 있습니다.

uint8_t __some_distinct_name[sizeof(YourTypeHere)];

컴파일 후 오브젝트 파일에서 크기를 가져옵니다.

$ nm -td -S your_object_file |       # list symbols and their sizes, in decimal
  grep ' __some_distinct_name$' |    # select the right one
  cut -d' ' -f2 |                    # grab the size field
  xargs printf "Your type is %d B\n" # print

이것은 모든 C 컴파일러용 범용 솔루션입니다.

우리의 목표가 그 가치를 아는 것이라면sizeof()그 값을 인쇄하는 대신 몇 가지 컴파일 시간을 평가하면 됩니다.sizeof(X)>??표현식을 사용하여 값을 좁힙니다.

이 트릭은 식이 다음과 같이 평가될 때 컴파일 시간 오류를 생성하는 것입니다.false(제로) 또는true(제로 이외).

많은 표준 C구조를 통해 우리의 목표를 달성할 수 있습니다.복제품case제가 따로 설명한 가치 트릭도 그 중 하나입니다.다른 하나는 컴파일러가 컴파일할 때 평가하는 이니셜라이저에서 0으로 나눗셈을 테스트하는 것입니다.예를 들어, X 의 사이즈를 취득하려면 , 다음의 순서에 따릅니다.

struct _X {
  int a;
  char c;
  double d;
  float f[30];
} X;

몇 줄의 컴파일:

#include <stdio.h>
struct _X {
  int a;
  char c;
  double d;
  float f[30];
} X;
int r2=1/(sizeof(X)<170);
int r3=1/(sizeof(X)<100);
int r4=1/(sizeof(X)<80);
int r5=1/(sizeof(X)<60);
int main()
{
   return 0;
}

결과

main.c:17:9: warning: division by zero [-Wdiv-by-zero]
 int r3=1/(sizeof(X)<100);
         ^
main.c:17:8: error: initializer element is not constant
 int r3=1/(sizeof(X)<100);
        ^
main.c:18:9: warning: division by zero [-Wdiv-by-zero]
 int r4=1/(sizeof(X)<80);
         ^
main.c:18:8: error: initializer element is not constant
 int r4=1/(sizeof(X)<80);
        ^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
 int r5=1/(sizeof(X)<60);
         ^
main.c:19:8: error: initializer element is not constant
 int r5=1/(sizeof(X)<60);
        ^

함축적sizeof(X)<170true(제로가 아닌) 단,sizeof(X)<100false(컴파일 시 0으로 나눗셈을 발생시킵니다.그런 다음 다른 값으로 테스트를 반복하여 실제 값을 얻을 수 있습니다.

#include <stdio.h>
struct _X {
  int a;
  char c;
  double d;
  float f[30];
} X;
int r2=1/(sizeof(X)<140);
int r3=1/(sizeof(X)<137);
int r4=1/(sizeof(X)<136);
int r5=1/(sizeof(X)!=136);

int main()
{
    return 0;
}

결과

main.c:18:9: warning: division by zero [-Wdiv-by-zero]
 int r4=1/(sizeof(X)<136);
         ^
main.c:18:8: error: initializer element is not constant
 int r4=1/(sizeof(X)<136);
        ^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
 int r5=1/(sizeof(X)!=136);
         ^
main.c:19:8: error: initializer element is not constant
 int r5=1/(sizeof(X)!=136);
        ^

그래서 우리는 안다sizeof(X)==136.

또는 를 사용하여?:오퍼레이터, 우리는 컴파일 시 평가되는 더 많은 C 언어 구조를 사용할 수 있습니다.어레이 선언을 사용한 Visual C++ 예제:

#include "stdafx.h"
struct X {
  int a;
  char b[30];
  double d;
  float f[20];
};
int a1[sizeof(X)<130?-1:1];
int a2[sizeof(X)<120?1:-1];
int a3[sizeof(X)==128?-1:1];

int _tmain(int argc, _TCHAR* argv[]){
  return 0;
}

결과

1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1>  cpptest.cpp
1>cpptest.cpp(11): error C2118: negative subscript
1>cpptest.cpp(12): error C2118: negative subscript
1>cpptest.cpp(13): error C2118: negative subscript
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

를 암시하다sizeof(X)<120>이 아니라 <130>이며, 128과 같습니다.

구조로는 안 돼프리프로세서는 컴파일이 실행되기 전에 호출되기 때문에 구조라는 개념조차 없습니다.존재하지 않거나 정의되지 않은 것의 크기를 평가할 수 없습니다.프리프로세서는 변환 유닛을 토큰화하지만 매크로 호출을 특정하기 위해서만 토큰화 합니다.

가장 가까운 것은 임베디드 타입의 사이즈에 맞추어 평가하는 실장 정의 매크로에 의존하는 것입니다.gcc에서는 다음 항목을 찾을 수 있습니다.

gcc -dM -E - </dev/null | grep -i size

내 시스템에서 인쇄된 내용:

#define __SIZE_MAX__ 18446744073709551615UL
#define __SIZEOF_INT__ 4
#define __SIZEOF_POINTER__ 8
#define __SIZEOF_LONG__ 8
#define __SIZEOF_LONG_DOUBLE__ 16
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_WINT_T__ 4
#define __SIZE_TYPE__ long unsigned int
#define __SIZEOF_PTRDIFF_T__ 8
#define __SIZEOF_FLOAT__ 4
#define __SIZEOF_SHORT__ 2
#define __SIZEOF_INT128__ 16
#define __SIZEOF_WCHAR_T__ 4
#define __SIZEOF_DOUBLE__ 8
#define __SIZEOF_LONG_LONG__ 8

프로그램을 작성하고 실행하지 않고는 커스텀 구조의 크기를 알 수 없습니다.

사용 중인 gcc C 컴파일러는 위의 솔루션 중 하나를 사용하여 크기 인쇄를 거부합니다.컴파일러의 경고를 어떤 크기로 삽입하는지 논리를 뒤집었습니다.

enum e
{
    X = sizeof(struct mystruct)
};

void foo()
{
    static enum e ev;

    switch (ev)
    {
    case 0:
    case 4:
    case 8:
    case 12:
    case 16:
    case 20:
        break;
    }
}

그럼 누락된 번호에 대한 경고를 살펴봐야겠네요.

warning: case value '0' not in enumerated type 'e' [-Wswitch]
warning: case value '4' not in enumerated type 'e' [-Wswitch]
warning: case value '12' not in enumerated type 'e' [-Wswitch]
warning: case value '16' not in enumerated type 'e' [-Wswitch]
warning: case value '20' not in enumerated type 'e' [-Wswitch]

그래서 내 구조 사이즈는 8이다.

짐은 4개입니다.

메흐... 그건 선택 사항이야

언급URL : https://stackoverflow.com/questions/20979565/how-can-i-print-the-result-of-sizeof-at-compile-time-in-c

반응형