전 처리기 매크로에서 "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
'IT박스' 카테고리의 다른 글
Git에서 HEAD는 무엇입니까? (0) | 2020.09.28 |
---|---|
C ++ 생성자 이름 뒤에 오는 콜론은 무엇을합니까? (0) | 2020.09.25 |
git 저장소의 기록에서 전체 디렉토리를 복원하는 방법은 무엇입니까? (0) | 2020.09.25 |
여유 디스크 공간 확보 (0) | 2020.09.25 |
값 대 엔터티 개체 (도메인 기반 디자인) (0) | 2020.09.25 |