IT박스

전 처리기 매크로에서 "sizeof"를 어떻게 사용할 수 있습니까?

itboxs 2020. 9. 25. 07:41
반응형

전 처리기 매크로에서 "sizeof"를 어떻게 사용할 수 있습니까?


sizeof전 처리기 매크로에서 를 사용하는 방법이 있습니까?

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

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

내가 여기서 확인하는 정확한 것은 완전히 구성되어 있습니다. 요점은 종종 이러한 유형의 (크기 또는 정렬) 컴파일 타임 검사를 삽입하여 잘못 정렬되거나 재조정 될 수있는 데이터 구조를 수정하는 사람을 보호하기를 좋아한다는 것입니다. 그것들을 깨뜨릴 크기의 것들.

말할 필요도없이 sizeof위에서 설명한 방식으로 a를 사용할 수없는 것 같습니다 .


어쨌든 sizeof전 처리기 매크로에서 " " 를 사용할 수 있습니까?

아니요. 조건부 지시문은 제한된 조건식 집합을 사용합니다. sizeof허용되지 않는 것 중 하나입니다.

전처리 지시문은 소스가 (적어도 개념적으로) 구문 분석되기 전에 평가되므로 아직 크기를 가져 오지 못한 유형이나 변수가 없습니다.

그러나 C에서 컴파일 타임 어설 션을 얻는 기술이 있습니다 (예 : 이 페이지 참조 ).


이를 수행하는 방법에는 여러 가지가 있습니다. 다음 스 니펫은 sizeof(someThing)같으면 코드를 생성하지 않습니다 PAGE_SIZE. 그렇지 않으면 컴파일 타임 오류가 발생합니다.

1. C11 방법

C11부터 사용할 수 있습니다 static_assert(필요 #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);

이 스레드는 정말 오래되었지만 ...

내 솔루션 :

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

해당 표현식이 0과 같으면 제대로 컴파일됩니다. 다른 것은 바로 거기에서 폭발합니다. 변수가 extern'd이기 때문에 공간을 차지하지 않으며 아무도 참조하지 않는 한 링크 오류가 발생하지 않습니다.

assert 매크로만큼 유연하지는 않지만 내 버전의 GCC에서 컴파일 할 수 없었고 이것은 거의 모든 곳에서 컴파일 될 것이라고 생각합니다.


나는 그것이 늦은 대답이라는 것을 알고 있지만 Mike의 버전에 추가하기 위해 여기에 메모리를 할당하지 않는 버전이 있습니다. 원래 크기 확인을하지 않았고, 몇 년 전에 인터넷에서 찾았고, 안타깝게도 저자를 참조 할 수 없습니다. 다른 두 가지는 동일한 아이디어의 확장입니다.

typedef이기 때문에 아무것도 할당되지 않습니다. 이름에 __LINE__이 있으면 항상 다른 이름이므로 필요한 곳에 복사하여 붙여 넣을 수 있습니다. 이것은 MS Visual Studio C 컴파일러 및 GCC Arm 컴파일러에서 작동합니다. 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];

다음 매크로는 어떻습니까?

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

The existing answers just show how to achieve the effect of "compile-time assertions" based on the size of a type. That may meet the OP's needs in this particular case, but there are other cases where you really need a preprocessor conditional based on the size of a type. Here's how to do it:

Write yourself a little C program like:

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

Compile that. Write a script in your favorite scripting language, which runs the above C program and captures its output. Use that output to generate a C header file. For example, if you were using Ruby, it might look like:

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

Then add a rule to your Makefile or other build script, which will make it run the above script to build sizes.h.

Include sizes.h wherever you need to use preprocessor conditionals based on sizes.

Done!

(Have you ever typed ./configure && make to build a program? What configure scripts do is basically just like the above...)


Just as a reference for this discussion, I report that some compilers get sizeof() ar pre-processor time.

JamesMcNellis answer is correct, but some compilers go through this limitation (this probably violates strict ansi c).

As a case of this, I refer to IAR C-compiler (probably the leading one for professional microcontroller/embedded programming).


#define SIZEOF(x) ((char*)(&(x) + 1) - (char*)&(x)) might work


In my portable c++ code ( http://www.starmessagesoftware.com/cpcclibrary/ ) wanted to put a safe guard on the sizes of some of my structs or classes.

Instead of finding a way for the preprocessor to throw an error ( which cannot work with sizeof() as it is stated here ), I found a solution here that causes the compiler to throw an error. http://www.barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99

I had to adapt that code to make it throw an error in my compiler (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];
};

In C11 _Static_assert keyword is added. It can be used like:

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

The sizeof operator is not available for the preprocessor, but you can transfer sizeof to the compiler and check the condition in runtime:

#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);
}

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

반응형