C макрос с #ifdef - PullRequest
       54

C макрос с #ifdef

1 голос
/ 13 марта 2020

Мне интересно, есть ли лучший способ реализации этого кода:

if (strcmp(port_p, all_ports_a[inc++]) == 0)
    {
        #ifdef GPIOA
            HAL_GPIO_WritePin(GPIOA, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE]));
            SER_send("Value written\r", strlen("Value written\r"));
            return 1;
        #endif
        //b
    }else if (strcmp(port_p, all_ports_a[inc++]) == 0){
        #ifdef GPIOB
            HAL_GPIO_WritePin(GPIOB, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE]));
            SER_send("Value written\r", strlen("Value written\r"));
            return 1;
        #endif
        //c
    }else if (strcmp(port_p, all_ports_a[inc++]) == 0){
        #ifdef GPIOC
            HAL_GPIO_WritePin(GPIOC, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE]));
            SER_send("Value written\r", strlen("Value written\r"));
            return 1;
        #endif
        //etc.

особенно эта часть:

#ifdef GPIOA
      HAL_GPIO_WritePin(GPIOA, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE]));
      SER_send("Value written\r", strlen("Value written\r"));
      return 1;
#endif

я хочу заменить это макросом, что-то как:

MY_MACRO (GPIOx, MESSAGE):

#ifdef GPIOx
      HAL_GPIO_WritePin(GPIOx, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE]));
      SER_send(MESSAGE, MESSAGE);
      return 1;
#endif

Я знаю, что мы не можем добавить #ifdef в макрос, но, возможно, я что-то пропустил? Одна строка вместо 5 была бы очень хороша!

Спасибо!

AJT

Ответы [ 2 ]

3 голосов
/ 13 марта 2020

Вы могли бы сделать что-то совершенно другое. Расположите данные в таблицах, затем найдите строку с соответствующим именем и используйте значения в строке.

Сначала определите таблицу со всеми необходимыми данными:

// Definition of single row
typedef struct {
    char name[NAME_MAX];
    GPIO_T gpio;
    char message[MESSAGE_MAX];
} Port_T;

// Table with all rows
Port_T const ports[] = {
#ifdef GPIOA
    { "GPIOA", GPIOA, "GPIOA message" },
#endif
#ifdef GPIOB
    { "GPIOB", GPIOB, "GPIOB message" },
#endif
 ...
};
// Number of rows on the table
size_t const portCount = sizeof ports / sizeof *ports;

Затем замените if/else цепочку на for l oop:

for(size_t i=0; i<portCount; ++i) {
    Port_T const * port = &ports[i];
    if(strcmp(port_p, port->name) == 0) {
        HAL_GPIO_WritePin(port->gpio, all_pins_a[offset], atoi(args[OFF_VALUE_WRITE]));
        SER_send(port->message, strlen(port->message));
        return 1;
    }
} 

Вы также можете использовать более сложные процедуры поиска, чем простой for l oop, например, двоичный поиск.

3 голосов
/ 13 марта 2020

Вот одно из возможных решений, хотя оно, вероятно, не является улучшением исходного кода!

#ifdef GPIOA
#define MY_MACRO_GPIOA(MESSAGE) MY_MACRO_(GPIOA, MESSAGE)
#else
#define MY_MACRO_GPIOA(MESSAGE) do; while (0)
#endif

#ifdef GPIOB
#define MY_MACRO_GPIOB(MESSAGE) MY_MACRO_(GPIOB, MESSAGE)
#else
#define MY_MACRO_GPIOB(MESSAGE) do; while (0)
#endif

#ifdef GPIOC
#define MY_MACRO_GPIOC(MESSAGE) MY_MACRO_(GPIOC, MESSAGE)
#else
#define MY_MACRO_GPIOC(MESSAGE) do; while (0)
#endif

#define MY_MACRO_(GPIOx, MESSAGE) \
    do { \
        HAL_GPIO_WritePin(GPIOx, all_pins_a[offset] , atoi(args[OFF_VALUE_WRITE])); \
        SER_send(MESSAGE, strlen(MESSAGE)); \
        return 1; \
    } while (0)

#define MY_MACRO(GPIOx, MESSAGE) MY_MACRO_##GPIOx(MESSAGE)

...

    if (strcmp(port_p, all_ports_a[inc++]) == 0)
        MY_MACRO(GPIOA, "Value written\r");
    else if (strcmp(port_p, all_ports_a[inc++]) == 0)
        MY_MACRO(GPIOB, "Value written\r");
    else if (strcmp(port_p, all_ports_a[inc++]) == 0)
        MY_MACRO(GPIOC, "Value written\r");
...