Более элегантный способ - сделать что-то подобное в некотором глобальном «mcu.h».
extern volatile const uint32_t SCI_PORTS; // number of supported ports
Затем в «mcu.c»:
#include "mcu.h"
#ifdef MCU_ABC_X
volatile const uint32_t SCI_PORTS = 2; // allocated at fixed address
#elif MCU_ABC_Y
volatile const uint32_t SCI_PORTS = 3; // allocated at fixed address
...
#endif
Тогдаваш массив всегда будет
#include "mcu.h"
const uint32_t baseaddr[] = {SCIA_BASE, SCIB_BASE, SCIC_BASE, SCID_BASE};
for(size_t i=0; i<SCI_PORTS; i++)
send(baseaddr[i], "hello world");
Вы используете только SCI_PORTS
количество элементов в этом массиве. Это позволяет разместить SCI_PORTS
по фиксированному адресу, например ячейке EEPROM, и вы получите тот же двоичный файл независимо от того, для какого члена семейства MCU вы компилируете.