programing

전처리기 매크로에서 "sizeof"를 사용하는 방법

prostudy 2022. 5. 20. 21:34
반응형

전처리기 매크로에서 "sizeof"를 사용하는 방법

A을(를) 사용할 수 있는 방법이 있는가?sizeof전처리기 매크로에서?

예를 들어, 몇 년 동안 다음과 같은 일을 하고 싶은 상황이 많이 있었다.

#if sizeof(someThing) != PAGE_SIZE
#error Data structure doesn't match page size
#endif

내가 여기서 확인하고 있는 정확한 것은 완전히 지어낸 것이다. 요점은, 나는 종종 데이터 구조를 잘못 조정하거나 그것들을 깨트릴 수 있는 크기를 재조정하는 사람을 경계하기 위해 이런 유형의 컴파일 타임 체크들을 넣기를 좋아한다.

말할 필요도 없이 - 나는 a를 사용할 수 없을 것 같다.sizeof상술한 방법으로

이것을 하는 데는 여러 가지 방법이 있다.다음 스니펫은 다음과 같은 경우 코드가 생성되지 않는다.sizeof(someThing)대등하다PAGE_SIZE; 그렇지 않으면 컴파일 시간 오류가 발생한다.

1. C11길

C11부터 사용할 수 있음(필수)#include <assert.h>).

사용량:

static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size");

2. 맞춤형 매크로

다음 시간 동안 컴파일 시간 오류만 얻으려면sizeof(something)예상한 매크로가 아니므로 다음 매크로:

#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

사용량:

BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE );

이 기사는 그것이 왜 작동하는지 자세히 설명한다.

3. MS별

Microsoft C++ 컴파일러에서는 C_ASSert 매크로(필수)를 사용할 수 있음#include <windows.h>)는 섹션 2에서 설명한 것과 유사한 트릭을 사용한다.

사용량:

C_ASSERT(sizeof(someThing) == PAGE_SIZE);

늦은 대답인 건 알지만 마이크의 버전에 덧붙이자면 여기 우리가 사용하는 버전이 있는데 어떤 메모리도 할당하지 않는다.나는 원래 사이즈 확인을 생각해내지 못했는데, 몇 년 전에 인터넷에서 찾았는데 아쉽게도 작가를 참조할 수가 없어.다른 두 사람은 같은 생각의 연장선에 불과하다.

그것들은 타이페프의 것이기 때문에, 아무것도 할당되지 않는다.이름에 _LINE__이 있으면, 필요한 곳에 복사하여 붙여넣을 수 있도록 항상 다른 이름이다.이것은 MS Visual Studio C 컴파일러와 GCC Arm 컴파일러에서 작동한다.CW는 CodeWarrior에서는 작동하지 않으며, CW는 _LINE__ 전처리기 구조를 사용하지 않고 재정립에 대해 불평한다.

//Check overall structure size
typedef char p__LINE__[ (sizeof(PARS) == 4184) ? 1 : -1];

//check 8 byte alignment for flash write or similar
typedef char p__LINE__[ ((sizeof(PARS) % 8) == 0) ? 1 : 1];

//check offset in structure to ensure a piece didn't move
typedef char p__LINE__[ (offsetof(PARS, SUB_PARS) == 912) ? 1 : -1];

"를 사용할 수 있는 방법이 있는가?sizeof"이전 매크로에서?

아니다. 조건부 지시문은 제한된 조건부 표현식을 사용한다.sizeof허용되지 않는 것 중 하나야

사전 처리 지시문은 선원을 구문 분석하기 전에 평가되므로(적어도 개념적으로), 아직 그 크기를 파악할 유형이나 변수가 없다.

그러나 C에는 컴파일 시간 주장을 얻는 기법이 있다(예: 이 페이지 참조).

기존 답변은 유형 규모에 따라 '비교적 시간 주장'의 효과를 얻는 방법만 보여준다.그것은 이 특별한 경우에 OP의 요구를 충족시킬 수 있지만, 당신이 정말로 타입의 크기에 근거한 전처리기 조건부가 필요한 다른 경우가 있다.다음 절차를 따르십시오.

다음과 같은 C 프로그램을 작성하십시오.

/* you could call this sizeof_int.c if you like... */
#include <stdio.h>
/* 'int' is just an example, it could be any other type */
int main(void) { printf("%zd", sizeof(int); }

그것을 컴파일하라.위의 C 프로그램을 실행하고 출력을 캡처하는 스크립팅 언어로 스크립트를 작성하십시오.이 출력을 사용하여 C 헤더 파일을 생성하십시오.예를 들어 루비를 사용하고 있다면 다음과 같이 보일 수 있다.

sizeof_int = `./sizeof_int`
File.open('include/sizes.h','w') { |f| f.write(<<HEADER) }
/* COMPUTER-GENERATED, DO NOT EDIT BY HAND! */
#define SIZEOF_INT #{sizeof_int}
/* others can go here... */
HEADER

그런 다음 Makefile 또는 다른 빌드 스크립트에 규칙을 추가하면 위의 스크립트를 실행하여 빌드할 수 있음sizes.h.

포함하다sizes.h크기에 따라 전처리기 조건을 사용해야 하는 곳.

알았어!

(타자를 쳐본 적이 있는가../configure && make프로그램을 만들려고?무엇configure스크립트 실행은 기본적으로 위와 같다...)

C11에서_Static_assert키워드가 추가된다.다음과 같이 사용할 수 있다.

_Static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size")

이 실이 정말 오래된 줄 알지만...

내 해결책:

extern char __CHECK__[1/!(<<EXPRESSION THAT SHOULD COME TO ZERO>>)];

그 표현이 0과 동일하다면, 그것은 괜찮다.다른 건 다 터지면 바로 저기서변수가 외부적이기 때문에 공간을 차지하지 않으며, 아무도 이를 참조하지 않는 한 링크 오류를 발생시키지 않을 것이다.

매크로처럼 유연하지는 않지만, 내 버전의 GCC에서 컴파일할 수 없었으니...어디서든 컴파일할 수 있을 것 같아

이 논의에 대한 참고자료로서, 나는 일부 컴파일러들이 사전 프로세서 시간 ()을 갖는다고 보고한다.

JamesMcNellis의 대답은 정확하지만, 일부 컴파일러들은 이러한 제한을 겪는다(이는 아마도 엄격한 ansi c를 위반할 것이다).

그 예로 IAR C-컴파일러(전문 마이크로컨트롤러/임베디드 프로그래밍의 선두주자일 가능성이 있음)를 언급한다.

다음 매크로:

/* 
 * Simple compile time assertion.
 * Example: CT_ASSERT(sizeof foo <= 16, foo_can_not_exceed_16_bytes);
 */
#define CT_ASSERT(exp, message_identifier) \
    struct compile_time_assertion { \
        char message_identifier : 8 + !(exp); \
    }

예를 들어 논평에서 MSVC는 다음과 같은 것을 말한다.

test.c(42) : error C2034: 'foo_can_not_exceed_16_bytes' : type of bit field too small for number of bits

sizeof전처리기에는 연산자를 사용할 수 없지만, 전송할 수 있음sizeof컴파일러로 이동하여 런타임에 상태를 확인하십시오.

#define elem_t double

#define compiler_size(x) sizeof(x)

elem_t n;
if (compiler_size(elem_t) == sizeof(int)) {
    printf("%d",(int)n);
} else {
    printf("%lf",(double)n);
}

#define SIZEOF(x) ((char*)(&(x) + 1) - (char*)&(x))아마 효과가 있을 것이다.

나의 휴대용 c++ 코드 (http://www.starmessagesoftware.com/cpcclibrary/ )는 나의 구조체나 수업의 일부의 크기를 안전하게 보호하기를 원했다.

전처리가 에러를 던질 수 있는 방법(여기서 언급된 크기()로는 작동할 수 없는 것)을 찾는 대신에, 나는 여기서 컴파일러가 에러를 던지게 하는 해결책을 찾았다.http://www.barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99

내 컴파일러(xcode)에 오류를 발생시키기 위해 그 코드를 조정해야 했다.

static union
{
    char   int8_t_incorrect[sizeof(  int8_t) == 1 ? 1: -1];
    char  uint8_t_incorrect[sizeof( uint8_t) == 1 ? 1: -1];
    char  int16_t_incorrect[sizeof( int16_t) == 2 ? 1: -1];
    char uint16_t_incorrect[sizeof(uint16_t) == 2 ? 1: -1];
    char  int32_t_incorrect[sizeof( int32_t) == 4 ? 1: -1];
    char uint32_t_incorrect[sizeof(uint32_t) == 4 ? 1: -1];
};

언급된 매크로의 것을 시험해본 결과, 이 파편은 원하는 결과를 만들어 내는 것 같다().t.h):

#include <sys/cdefs.h>
#define STATIC_ASSERT(condition) typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(int) == 42);

달리기cc -E t.h:

# 1 "t.h"
...
# 2 "t.h" 2

typedef char _static_assert_3[ (sizeof(int) == 4) ? 1 : -1];
typedef char _static_assert_4[ (sizeof(int) == 42) ? 1 : -1];

달리기cc -o t.o t.h:

% cc -o t.o t.h
t.h:4:1: error: '_static_assert_4' declared as an array with a negative size
STATIC_ASSERT(sizeof(int) == 42);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.h:2:84: note: expanded from macro 'STATIC_ASSERT'
  ...typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
                                                       ^~~~~~~~~~~~~~~~~~~~
1 error generated.

42는 결국 모든 것에 대한 해답이 아니다...

컴파일 시간에 데이터 구조의 크기를 제약조건과 비교하기 위해 나는 이 방법을 사용했다.

#if defined(__GNUC__)
{ char c1[sizeof(x)-MAX_SIZEOF_X-1]; } // brakets limit c1's scope
#else
{ char c1[sizeof(x)-MAX_SIZEOF_X]; }   
#endif

x의 크기가 한계 MAX_SIZEOF_X보다 크거나 같으면 gcc는 '배열 크기가 너무 크다'는 오류로 불평할 것이다.VC++는 오류 C2148('배열의 총 크기가 0x7ffffffffff바이트를 초과하지 않아야 함') 또는 C4266 '상수 크기 0의 배열을 할당할 수 없음'을 발생시킨다.

gcc는 제로 사이즈의 배열을 이러한 방식으로 정의(x - n의 크기)할 수 있기 때문에 두 가지 정의가 필요하다.

참조URL: https://stackoverflow.com/questions/4079243/how-can-i-use-sizeof-in-a-preprocessor-macro

반응형