입신의 매거 구조체 함수 성명

6101 단어 코드 세그먼트
STM32 인터럽트 벡터표의 코드를 대신이 고친 것을 보고 오늘 우리는'대신'이 쓴 매거, 구조, 함수 성명, 또는 같은 레시피, 같은 소뇌를 살펴본다.
잔말 말고 코드부터 넣으세요.첫 번째 단락은 매거진이고, 두 번째 단락은 함수이며, 세 번째 단락은 하나의 수조에 대한 초기화이다.
//==============================================================================
#define UTIL_EVENT_Define(T,X)    
#define UTIL_STATE_Define(T,X)    UTIL_STATE_ENUM(T,X),    
enum
{
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
};
#undef UTIL_STATE_Define  
#undef UTIL_EVENT_Define
//==============================================================================

//==============================================================================
#define UTIL_STATE_Define(T,X)    UTIL_STATE_FUNC_Extern(T,X) 
#define UTIL_EVENT_Define(T,X)
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
#undef UTIL_STATE_Define 
#undef UTIL_EVENT_Define
//==============================================================================

//==============================================================================
#define UTIL_STATE_Define(T,X)    UTIL_STATE_FUNC_ITEM_IN_TAB(T,X),
#define UTIL_EVENT_Define(T,X)
const __pgm __state_func_t APP_PROC_STATE_M_NET_SETUP_TAB[]=
{
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
};
#undef UTIL_STATE_Define 
#undef UTIL_EVENT_Define

이 APPPROC_STATE_M_NET_SETUP_define.h 헤더 파일의 내용은 비교적 많지만 항목마다 대동소이하기 때문에 나는 여기에 일부분을 놓을 것이다.
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,BEGIN)
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,END)
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,AT_E0)

UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,AT_CPIN)

관중들이 이 코드를 처음 읽었을 때 그 안의 비결을 바로 이해했는지 모르겠다.이런 코드를 쓸 수 있는 사람은 컴파일러에 대한 이해가 깊고 C 언어의 공력이 깊다. 그렇지 않으면 대신이라고 할 수 없다.이제 내가 그 안의 비결을 잘 이해할게.
먼저 #include에 대한 이해입니다.평소에 우리는 하나의 모듈의 대외적인 함수 성명, 구조체 매거 정의, 변수 성명 등,include 그 모듈의 헤더 파일을 가져와야 한다는 것을 알고 있다.이것은 단지 사용할 뿐입니다. 사실include의 본질은 지정한 헤더 파일의 내용을 #include로 바꾸는 것입니다. 물론 이 동작은 컴파일러가 실행하는 것입니다.
예를 들다
//ModuleA.h

extern uint8_t Test;
uint8_t GetFun(void);
//ModuleB.c


#include "ModuleA.h"


....
....
....

모듈 B의 c 파일에는 모듈 A의 헤더 파일이 포함되어 있습니다.컴파일러가 컴파일할 때, 먼저 모듈 B의 c 파일을 이렇게 만든 후에야 컴파일한다.
//ModuleB.c

extern uint8_t Test;
uint8_t GetFun(void);



...
...
...

매크로 정의의 본질은 #include와 같습니다. 컴파일러는 컴파일하기 전에 코드의 매크로를 정의된 내용으로 바꿉니다.
이런 것들을 이해했으니, 우리는 처음에 그 코드의 매거 정의를 가지고 보자
#define UTIL_EVENT_Define(T,X)    
#define UTIL_STATE_Define(T,X)    UTIL_STATE_ENUM(T,X),    
enum
{
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
};
#undef UTIL_STATE_Define  
#undef UTIL_EVENT_Define

즉, 컴파일러가 컴파일할 때 APP 를PROC_STATE_M_NET_SETUP_define.h 파일의 내용'붙여넣기'가 매거 정의에 들어가면'붙여넣기'효과를 복원해 봅시다
#define UTIL_EVENT_Define(T,X)    
#define UTIL_STATE_Define(T,X)    UTIL_STATE_ENUM(T,X),    
enum
{
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,BEGIN)
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,END)
UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,AT_E0)

UTIL_STATE_Define(APP_PROC_STATE_M_NET_SETUP_t,AT_CPIN)
};
#undef UTIL_STATE_Define  
#undef UTIL_EVENT_Define

이때 유의하세요. 매거 정의를 내리기 전에 UTILSTATE_Define 매크로를 정의합니다. 실제 상황은 이렇습니다.
enum
{
UTIL_STATE_ENUM(APP_PROC_STATE_M_NET_SETUP_t,BEGIN),
UTIL_STATE_ENUM(APP_PROC_STATE_M_NET_SETUP_t,END),
UTIL_STATE_ENUM(APP_PROC_STATE_M_NET_SETUP_t,AT_E0),

UTIL_STATE_ENUM(APP_PROC_STATE_M_NET_SETUP_t,AT_CPIN),
};

그럼 이 UTILSTATE_ENUM 매크로는 또 어떤 정의입니까? 다른 헤더 파일에서 찾았습니다.
#define UTIL_STATE_ENUM(T,X)              STATE_ENUM_##T##_##X

자, 그럼 매거진의 궁극적인 전개는 이렇다. 이름은 정말...아이고, 길다, 길다.
enum
{
STATE_ENUM_APP_PROC_STATE_M_NET_SETUP_t_BEGIN,
STATE_ENUM_APP_PROC_STATE_M_NET_SETUP_t_END,
STATE_ENUM_APP_PROC_STATE_M_NET_SETUP_t_AT_E0,
STATE_ENUM_APP_PROC_STATE_M_NET_SETUP_t_AT_CPIN,
};

이 코드 다음에 또 재미있는 곳이 있는데, 바로 방금 이 APPPROC_STATE_M_NET_SETUP_define.h 파일은 매거 정의에만 사용되는 것이 아니라 함수 성명과 그룹 초기화에도 사용된다.이걸 어떻게 했지?
함수 성명 부분을 살펴보자.
#define UTIL_STATE_Define(T,X)    UTIL_STATE_FUNC_Extern(T,X) 
#define UTIL_EVENT_Define(T,X)
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
#undef UTIL_STATE_Define 
#undef UTIL_EVENT_Define

진계적, 함수 정의 전에 UTILSTATE_Define 이 매크로는 다시 정의되었습니다. 이 매크로는 헤더 파일에 있는 것입니다.UTIL_STATE_FUNC_Extern 매크로의 정의는 다음과 같습니다.
#define UTIL_STATE_FUNC(T,X)              STATE_FUNC_##T##_##X
#define UTIL_STATE_FUNC_INLINE(T,X)       STATE_FUNC_##T##_##X##_
#define UTIL_STATE_FUNC_Extern(T,X)       void UTIL_STATE_FUNC(T,X)(UTIL_EVENT_STATE_t *p_es);

또 각종 패치가 매크로해서 머리가 어지러워서 나는 전개하지 않았다. 어쨌든 그는 이런 방법을 통해 한 무더기의 함수를 정의했고 함수의 이름은 컴파일러가 컴파일할 때 패치했다.더욱이 그는 함수 정의를 한 후에 #undef가 이전에 정한 매크로를 써서 뒤에 잘못 쓰는 것을 방지했다.
마지막으로, 우리는 수조의 초기화를 보았다.
#define UTIL_STATE_Define(T,X)    UTIL_STATE_FUNC_ITEM_IN_TAB(T,X),
#define UTIL_EVENT_Define(T,X)
const __pgm __state_func_t APP_PROC_STATE_M_NET_SETUP_TAB[]=
{
#include "APP_PROC_STATE_M_NET_SETUP_define.h"
};
#undef UTIL_STATE_Define 
#undef UTIL_EVENT_Define

여전히 같은 수법이야, 우린 UTIL만 봤어STATE_FUNC_ITEM_IN_TAB 이 매크로는 그룹이 어떻게 초기화되었는지 알게 되었다.
#define UTIL_STATE_FUNC_ITEM_IN_TAB(T,X)  [UTIL_STATE_ENUM(T,X)]=UTIL_STATE_FUNC(T,X)

이것은 이전에 매거진과 함수 정의의 연결 매크로를 사용했다.매거, 함수 성명, 수조 초기화, 합쳐서 하나의 함수 바늘 수조를 정의하고 매거로 색인을 해서 함수 이름을 수조의 초기화에 쓰는 것이 전체적인 생각이다.
확실히, 이 조작을 통해 많은 코드를 적게 썼는데, 이 코드들은 모두 컴파일러 스스로 완성했다.하지만 가독성은 누가 봐도 안다.
여기를 보면 여러분도 저와 같은 의문이 있으실 거예요. 이렇게 매거, 함수를 화려하게 정의해 주셨는데 사용할 때 어떻게 해요?다른 것이 아니라, 그래도 홍을 연결하는 데 의지해야 한다.예를 들면 매거에 쓰려면 오직 이렇게 할 수밖에 없다
UTIL_STATE_ENUM(APP_PROC_STATE_M_NET_SETUP_t,BEGIN)

이런 코드는 우선 가독성이 매우 떨어지고 맞춤법 매크로를 남용하여 읽는 사고방식을 자주 끊는다. 가장 얄미운 것은 함수의 이름을 맞춤법으로 하는 것이다. 디버깅을 할 때 정의로 바로 넘어가지 못하고 검색을 하려고 해도 손댈 수가 없어 효율이 떨어진다.함수 이름이 맞춤법으로 연결되는 것도 매우 나쁜 영향을 미친다. 바로 컴파일링이 잘못되었을 때 오류 메시지에서 함수의 이름은 컴파일러가 매크로를 완전히 펼친 후의 이름이다. 함수의 이름을 보면 매우 낯설고 혼란스러워서 어느 함수인지 단번에 떠올릴 수 없을 것이다.이런 코드는 컴파일러와 C 언어에 대한 이해를 향상시키는 데도 적합하다.

좋은 웹페이지 즐겨찾기