Я уверен, что вы слышали слово «X Macro» в C, которым вы можете подытожить общий код вашего конкретного раздела в вашей программе. Я использую ту же концепцию, чтобы уменьшить количество строк в моем (визуальном) коде и позволить компьютеру писать код за меня. Прежде чем перейти к примеру, просто посмотрите на определение X-macro.

X-Макро

X-Macros основаны на свойстве вложенных макросов и возможности определять макросы внутри других макросов. X-Macros — очень мощный метод препроцессора в том смысле, что он может создавать самостоятельныйи взаимозависимый фрагмент кода.

Ниже приведен код с примером X-Macro,

#include <stdio.h>
#define ALL_EVENTS \
    X(EVENT_1)     \
    X(EVENT_2)     \
    X(EVENT_3)     \
    X(EVENT_4)
#define ALL_STATES \
    X(STATE_1)     \
    X(STATE_2)     \
    X(STATE_3)     \
    X(STATE_4)
typedef enum _event_ {
    #define X(arg) arg,
        ALL_EVENTS
    #undef X
}EVENTS;
typedef enum _state_ {
    #define X(arg) arg,
        ALL_STATES
    #undef X
}STATES;
void print_event_state(EVENTS event, STATES state) {
    switch(event) {
        #define X(arg) case arg : printf("Event = "#arg); \
                       break;
            ALL_EVENTS
        #undef X
    }
 
    switch(state) {
        #define X(arg) case arg : printf(", State = "#arg"\n"); \
                       break;
            ALL_STATES
        #undef X
    }
}
int main() {
    print_event_state(EVENT_1, STATE_4);
    print_event_state(EVENT_2, STATE_3);
    print_event_state(EVENT_3, STATE_2);
    print_event_state(EVENT_4, STATE_1);
}

Давайте обсудим, как препроцессор расширяет этот макрос.

Первый препроцессор разворачивает макрос ALL_EVENTS & ALL_STATE как,

typedef enum _event_ {
    #define X(arg) arg,
        X(EVENT_1)
        X(EVENT_2)
        X(EVENT_3)
        X(EVENT_4)
    #undef X
}EVENTS;
typedef enum _state_ {
    #define X(arg) arg,
        X(STATE_1)
        X(STATE_2)
        X(STATE_3)
        X(STATE_4)
    #undef X
}STATES;
switch(event) {
    #define X(arg) case arg : printf("Event = "#arg); \
               break;
        X(EVENT_1)
        X(EVENT_2)
        X(EVENT_3)
        X(EVENT_4)
    #undef X
}
 
switch(state) {
    #define X(arg) case arg : printf(", State = "#arg"\n"); \
                   break;
        X(STATE_1)
        X(STATE_2)
        X(STATE_3)
        X(STATE_4)
    #undef X
}

Затем он расширяет X (СОБЫТИЕ) и X (СОСТОЯНИЕ) как,

typedef enum _event_ {
    EVENT_1,
    EVENT_2,
    EVENT_3,
    EVENT_4,
}EVENTS;
typedef enum _state_ {
    STATE_1,
    STATE_2,
    STATE_3,
    STATE_4,
}STATES;
switch(event) {
    case EVENT_1 : printf("Event = ""EVENT_1);
                   break;
    case EVENT_2 : printf("Event = ""EVENT_2);
                   break;
    case EVENT_3 : printf("Event = ""EVENT_3);
                   break;
    case EVENT_4 : printf("Event = ""EVENT_4);
                   break;
}
switch(state) {
    case STATE_1 : printf(", State = ""STATE_1""\n");
                   break;
    case STATE_2 : printf(", State = ""STATE_2""\n");
                   break;
    case STATE_3 : printf(", State = ""STATE_3""\n");
                   break;
    case STATE_4 : printf(", State = ""STATE_4""\n");
                   break;
}

Таким образом, вы можете не только написать менее (визуальный) код, но и сделать код взаимозависимым. Предположим сценарий, в котором вам нужно будет добавить несколько событий и состояний. Вместо того, чтобы писать и добавлять везде в коде, вы можете просто добавить в одном месте, и ваш код готов к расширению.!!