C에서 매크로를 사용하는 이유
중복 가능성:
C 매크로는 무엇에 도움이 됩니까?
몇 달마다 대학 프로그래밍 교육에서 다루지 못한 C학점을 배우고 싶어 안달이 나요.오늘날에는 매크로입니다.매크로에 대한 기본적인 이해는 매크로가 컴파일되기 전에 코드에서 발생하는 단순한 검색 및 치환이라는 것입니다.왜 매크로를 사용하는지 이해가 안 돼요.제가 보고 있는 대부분의 기본적인 예는 다음과 같습니다.
TEST(a,%d);
#define TEST(a,b) printf(" The value of " #a " = " #b " \n", a)
//which expands to
printf(" The value of a = %d \n",a);
(여기서부터)
제 초보자의 관점에서 새로운 기능을 정의하면 같은 결과를 얻을 수 있을 것 같습니다.검색과 교환이 쉬워지기 전에 매크로가 많은 소스를 빠르게 수정하는 데 역사적으로 얼마나 유용한지 알 수 있지만, 뭔가 더 큰 포인트를 놓치고 있는 것 같습니다.
그렇다면 매크로가 당신에게 어떤 도움이 될 수 있을까요?
검색과 교환이 아니라 토큰 확장입니다.C매크로는 컴퓨터 세계에서 다른 모든 종류의 매크로와 같습니다.짧고 간단한 것을 써서 자동으로 길고 복잡한 것으로 바꾸는 방법입니다.
매크로가 사용되는 이유 중 하나는 퍼포먼스입니다.컴파일러에 대해 자주 무시되는 힌트인 "inline" 키워드와 달리 항상 인라인으로 확장되기 때문에 함수 호출 오버헤드를 제거하는 방법입니다.또, C99 이전에는 (표준에는) 존재하지도 않았습니다.예를 들어 select 및 pselect에서 사용되는 fd_sets와 함께 사용되는 매크로의 FD_ 패밀리를 참조하십시오.이들 fd_set은 실제로는 비트셋일 뿐이며 FD_매크로는 비트 트위들링 조작을 숨기고 있습니다.매번 빈둥빈둥 쓴다는 것은 귀찮은 일이며, 인라인을 사용하지 않으면 함수 호출에 많은 오버헤드가 발생합니다.
또한 매크로는 기능하지 않는 몇 가지 작업을 수행할 수 있습니다.토큰 붙여넣기를 검토합니다.프리프로세서는 컴파일러보다 먼저 실행되므로 컴파일러가 사용할 새로운 식별자를 만들 수 있습니다.이를 통해 유사한 정의를 많이 작성할 수 있습니다.
#define DEF_PAIR_OF(dtype) \
typedef struct pair_of_##dtype { \
dtype first; \
dtype second; \
} pair_of_##dtype##_t
DEF_PAIR_OF(int);
DEF_PAIR_OF(double);
DEF_PAIR_OF(MyStruct);
/* etc */
함수가 수행할 수 없는 또 다른 작업은 컴파일 시간 정보를 런타임 정보로 변환하는 것입니다.
#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else
#define REPORT_PTR_VALUE(v)
#endif
void someFunction(const int* reallyCoolPointer) {
REPORT_PTR_VALUE(reallyCoolPointer);
/* Other code */
}
매크로처럼 함수가 출력에 파라미터 이름을 사용할 수 있는 방법은 없습니다.또, 릴리스 빌드의 디버깅코드를 컴파일 하는 방법도 나타냅니다.
C99까지는 인라인 키워드가 C언어에서는 표준이 아니었기 때문입니다.따라서 매크로를 사용하면 작은 함수를 인라인화할 수 있습니다.또한 어떤 면에서는 템플릿과 같이 작동합니다. 즉, 매크로 정의에서 유형을 지정할 필요가 없습니다.
#define MAX(x,y) ((x) > (y) ? (x) : (y))
이 매크로는 정수, 배수, 플로트 등에 준거합니다.
매크로는 컴파일 시 확장됩니다.디버깅 메시지가 자주 악용되는 것은 맞지만 C의 전형적인 예로는 디버깅메시지를 쓰는 매크로가 있습니다.디버깅메시지는 (컴파일시에 디버깅모드가 꺼졌을 때) 어떤 코드도 생성되지 않기 때문에 속도가 느려지지 않습니다.
로깅을 수행할 수 있지만 디버깅모드만 실행할 수 있습니다.그래서 이렇게 씁니다.
#ifdef DEBUG
#define LOG_MSG(x) printf(x);
#else
#define LOG_MSG(X)
#endif
컴파일 타임 스위치를 기반으로 무언가를 끄거나 켜야 할 때가 있습니다. 예를 들어, 우리 회사가 우리 제품의 공동 브랜딩을 하는데 파트너들이 꺼달라고 합니다.다음과 같은 작업을 수행합니다.
#ifndef SPECIAL_PARTNER_BUILD
DoSomethingReallyAwesome();
#endif
그런 다음 파트너에게 드롭을 제공할 때 -DSPECIAL_PARTNER_BUILD를 사용하여 구축합니다.
다른 많은 가능한 이유들 중에.
때로는 몇 번이고 반복해서 타이핑하는 것을 저장하고 싶을 때도 있습니다.어떤 사람들은 이것을 멀리 가져가서(MFC의 기침) 어려운 API를 추출하기 위해 매크로에서 자신의 언어에 해당하는 것을 씁니다.이로 인해 디버깅은 악몽이 됩니다.
C 매크로는 컴파일 시에 코드를 생성할 수 있습니다.이는 새로운 키워드와 동작을 사용하여 도메인 고유의 언어를 효과적으로 작성하기 위해 사용할 수 있습니다.
제가 가장 좋아하는 예 중 하나는 매크로를 통해 C에 코루틴을 구현하는 Simon Tatham의 방법입니다.구현되는 가장 간단한 매크로는 다음과 같습니다.
#define crBegin static int state=0; switch(state) { case 0:
네, 타의 추종을 불허하는 버팀대로요.다른 매크로로 해결할 수 있습니다.
코드에는 다음과 같은 매크로가 사용되었습니다.
// convenience macros for implementing field setter/getter functions
#ifndef CREATE_GET_SET
#define CREATE_GET_SET(PREFIX, FIELD_NAME,FIELD_DATATYPE) \
protected:\
FIELD_DATATYPE PREFIX ## FIELD_NAME;\
public:\
inline FIELD_DATATYPE get ## _ ## FIELD_NAME(void) const\
{ \
return(PREFIX ## FIELD_NAME); \
} \
inline void set ## _ ## FIELD_NAME(FIELD_DATATYPE p) \
{ \
PREFIX ## FIELD_NAME = p; \
}
#endif
클래스/클래스 내에서 변수를 정의할 수 있습니다.
CREATE_GET_SET(_, id, unsigned int);
그러면 변수가 정의되고 코드의 범용 getter/setter가 생성됩니다.get/set을 위한 보다 깨끗하고 일관된 코드 생성을 가능하게 합니다.물론 모두 쓸 수 있지만, 이것은 많은 종류의 상용 코드입니다.참고: 이것은 몇 개의 매크로 중 하나일 뿐입니다.다 안 올렸어요."char *"라고 말하는 것은 이 방법으로는 처리할 수 없습니다(세트에서 데이터를 strncpy 또는 strcpy로 설정합니다).이것은, 매크로와 몇개의 간단한 타입으로 할 수 있는 간단한 데모에 지나지 않습니다.
매크로는 사물처럼 기능하는 것 말고도 여러 가지 용도로 사용할 수 있습니다.
매직 넘버나 문자열에 매크로를 사용하면 매우 편리합니다.
#define MY_MAGIC_NUM 57
/*MY_MAGIC_NUM used all through out the code*/
퍼포먼스가 높은 시나리오에서는 매크로를 사용하여 "자동" 루프 롤링을 생성할 수 있습니다.최신 컴파일러는 이 기능을 더 잘 사용할 수 있지만 예전에는 이 기능이 유용했습니다.
컴파일러는 타깃머신에 대한 자세한 내용을 알고 있는 경우가 많기 때문에 조건부 컴파일을 사용하여 빅 엔디안 프로세서용 코드와 리틀 엔디안 프로세서용 코드를 각각 가질 수 있습니다.이것에 의해, 다른 프로세서 전용의 코드로 코드가 부풀어 오르는 것을 막을 수 있습니다.
예를 들어, 특정 시스템의 어셈블리 코드가 있지만 다른 시스템의 어셈블리 코드는 C 코드입니다.
가장 큰 장점은 '파일 설정'으로 사용할 때 있다고 생각합니다.
#define USE_FAST_AGORHITM
//#define USE_SLOW_ONE
글로벌 '상수'
#define MAX_NUMBER_OF_USERS 100000
대부분의 프로그램은 매크로로 작성되어 있습니다(예를 들어 Brian Gladman의 AES 구현 http://www.gladman.me.uk/cryptography_technology/index.php 참조).
매크로에서 함수의 코드가 호출자의 코드 스트림에 삽입됩니다.이것은, 다른 많은 것에 의해서 퍼포먼스가 향상될 가능성이 있습니다.옵티마이저가 착신 코드를 순서적으로 통합할 수 있기 때문입니다.착신 코드를 발신자에 최적화할 수 있기 때문입니다.다만, 매크로의 인수 타입은 체크되지 않기 때문에 주의해 주세요.인라인 함수(C++도 사용하고 있는 경우)와 약간의 매크로에 대한 적절한 참조는 다음과 같습니다.http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5
언급URL : https://stackoverflow.com/questions/1358232/why-use-macros-in-c
'programing' 카테고리의 다른 글
pwa가 db가 아닌 api 캐시를 고려하는 것이 잘못되었습니까? (0) | 2022.08.21 |
---|---|
리스트는 리스트의 서브클래스입니까? Java 제네릭이 암묵적으로 다형성이 아닌 이유는 무엇입니까? (0) | 2022.08.21 |
vue.js에서 어레이 개체 속성에 액세스하는 중 (0) | 2022.08.21 |
자바에서 부호 없는 바이트를 만들 수 있나요? (0) | 2022.08.21 |
Vuejs Ajax 콜 및 데이터 테이블 (0) | 2022.08.21 |