Использование #define для части (суффикса) идентификатора

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Есть блоки следующего вида:

 

firstVal_0 = ...

secondArray_0[...] =...

thirdFunction_0_a();

 

и

 

firstVal_1 = ...

secondArray_1[...] =...

thirdFunction_1_a();

 

понятно, что можно создать объект, куда запихать все свойства и методы, а поторм использовать массив объектов.

Но хочется данную последовательность инструкций запихнуть в include-файл, а перед этим определить фрагменты имен "_0" или "_1", чтобы выбирать те или иные переменные, массивы, функции.

Насколько я понимаю, в обычном случае можно определить только идентификатор целиком, а можно ли определить и использовать его часть (суффикс)? Если можно, как это будет выглядеть?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, конечно можно. Для этого используется операция ##

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Спасибо, но что-то пошло не так:

Хочу получить:

new_note_0[0]

определяю:

#define LOC_INDEX 0 // индекс в массиве-очереди команд
#define V_INDEX 0 // номер голоса
#define GLUE(item, index) item##_##index

вставляю из файла:

  if(GLUE(new_note, V_INDEX)[LOC_INDEX]) {
...

Synt_2560_04.ino:73:27: note: in definition of macro 'GLUE'
D:\Arduino\MySketches\Synt_2560_04\int_check_new_note.d:1:11: error: 'new_note_V_INDEX' was not declared in this scope
   if(GLUE(new_note, V_INDEX)[LOC_INDEX]) {
           ^
Synt_2560_04.ino:73:27: note: in definition of macro 'GLUE'
Error compiling.

 

Перестановка местами дефайнов проблему не решает.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, всё правильно. Она не делает подстановки перед конкатенацией, поэтому V_INDEX так и остаётся V_INDEX и не становится 0.

Напишите просто 0 - отлично всё сделается.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

"0" написать не могу - нужна именно константа, переопределяемая снаружи.

Т.е. в том файле, где есть строка

if(GLUE(new_note, V_INDEX)[LOC_INDEX]) {

должен быть именно V_INDEX, но никак не "0", т.к. "0" задается снаружи - в другом файле.

Как поступить в этом случае?

 

Еще раз, чтобы было понятнее:

есть файл, в котором строчки:

 

#define LOC_INDEX 0 // индекс в массиве-очереди команд
#define V_INDEX 0 // номер голоса
#define GLUE(item, index) item##_##index

#include "abcd.d"

#define V_INDEX 1 // номер голоса

#include "abcd.d"

 

А в файле abcd.d есть строчка

 

if(GLUE(new_note, V_INDEX)[LOC_INDEX]) {

 

и нужно, чтобы при первом включении файла abcd.d получалось:

new_note_0[0]

а при втором:

new_note_1[0]

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Я могу сделать так:

#define LOC_INDEX 0 // индекс в массиве-очереди команд
#define V_INDEX 0 // номер голоса
#define GLUE(item) item##_0

#include "abcd.d"

#define V_INDEX 1 // номер голоса

#define GLUE(item) item##_1

#include "abcd.d"

 

А в файле abcd.d:

 

if(GLUE(new_note)[LOC_INDEX]) {

 

Но это неизящно для одной и той же сущности (обозначенной V_INDEX) использовать два дефайна и, самое главное, следить за тем, чтобы они изменялись строго синхронно. Мне казалось, что дефайны для того и нужны, чтобы избавиться от необходимости отслеживать синхронные изменения ручками/глазками.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не, ну, поймите, подстановка не происходит только если используется ##. В других случаях всё подставляется как обычно. Поэтому Вашу проблему надо решать промежуточным макросом в котором нет ## и всё подставится нормально. Промежуточный макрос просто вызывает основной, но передаёт ему уже "подставленные" значения своих параметров. Вот смотрите


#define LOC_INDEX 0 // индекс в массиве-очереди команд
#define V_INDEX 0 // номер голоса

#define _GLUE(item, index) item##_##index   // Этот макрос получит параметры уже после подстановки
#define GLUE(item,index) _GLUE(item,index)  // Промежуточный макрос, чтобы всё подставилось

void setup(){
	char new_note_0[2] = {1,2};
 	Serial.print(GLUE(new_note, V_INDEX)[LOC_INDEX]);
}

void loop(){}

Понятно?

У меня это нормально компилируется.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Спасибо, на первый взгляд заработало (правда, пока не понял, почему), а разбираться буду зав... нет, уже сегодня, но ближе ко второй половине дня.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не за что. И должно было заработать. При разборе первого макроса вместо V_INDEX подставился ноль и уже нулём был передан второму макросу. Вот и вся хитрость. Удачи!

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

И правда "хитрость".

Спасибо.