Search code examples
cmacrosvariadic-macros

Variadic macros didn't work


What I want to do is access code with macros. But the complier gives me this error

identifier "BUTTON___button" is undefined

#define BUTTON_1                HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8)
#define BUTTON_2                HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9)
#define BUTTON_3                HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)
#define BUTTON_4                HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5)
#define BUTTON_5                HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)
#define BUTTON_6                HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_14)
#define BUTTON_7                HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_12)
#define BUTTON_8                HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_11)
#define BUTTON_9                HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15)
#define BUTTON_10               HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_0)
#define BUTTON_11               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_10)
#define BUTTON_12               HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
#define BUTTON_13               HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)
#define BUTTON_14               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_2)
#define BUTTON_15               HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11)
#define BUTTON_16               HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2)
#define BUTTON_17               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0)
#define BUTTON_18               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1)
#define BUTTON_19               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5)
#define BUTTON_20               HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4)

#define BUTTON(...)             BUTTON_##__VA_ARGS__


for(uint8_t _button = 1; _button < 21; _button++)
    BUTTON(__button) //=> This should give me BUTTON(1) , BUTTON(2) ... each iteration.But not working

By using variadic macros, can I get what I want?


Solution

  • You must remember that preprocessor things happen before the code is compiled, and is strictly text-only replacement.

    Thus, depending on a variable that has different values because of a run-time loop makes no sense, and doesn't work.

    The proper way to do this is to put the port addresses (GPIOA etc) in an array, together with the corresponding pin for each port:

    static const struct {
      const GPIO_TypeDef *port;
      uint32_t            pin;
    } buttons[] = {
      { GPIOB, GPIO_PIN_8 },
      { GPIOB, GPIO_PIN_9 },
      ...
    };
    

    then iterate over the data in the array:

    for (size_t i = 0; i < sizeof buttons / sizeof *buttons; ++i)
    {
      if (HAL_GPIO_ReadPin(buttons[i].port, buttons[i].pin))
      {
         ...
      }
    }