Мне нужно сделать некоторые назначения следующим образом.
В структуре REGS тайлы упорядочены по именам;
а снаружи плитки располагаются по индексам.
#include <stdio.h>
typedef struct TILE {} TILE;
typedef struct REGS {
TILE tile00, tile01, tile02,
tile10, tile11, tile12,
tile20, tile21, tile22;
} REGS;
int main() {
TILE tiles[3][3];
REGS regs;
regs.tile00 = tiles[0][0];
regs.tile01 = tiles[0][1];
regs.tile02 = tiles[0][2];
regs.tile10 = tiles[1][0];
regs.tile11 = tiles[1][1];
regs.tile12 = tiles[1][2];
regs.tile20 = tiles[2][0];
regs.tile21 = tiles[2][1];
regs.tile22 = tiles[2][2];
return 0;
}
поэтому я полагаю, мне нужен цикл вроде:
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
// not real code
regs.tile##i##j = tiles[i][j];
}
}
для этого я определил несколько макросов:
#define TILE_MEM(prefix, i, j) prefix##i##j
#define WRITE_TILE(base, mem, value) (base.mem = value;)
#define MACRO_LOOP(i,j) (WRITE_TILE(regs, TILE_MEM(tile, i, j), tiles[i][j]))
тогда я сделал это:
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
MACRO_LOOP(i, j);
}
}
но он не компилируется.
ПОЖАЛУЙСТА ПОМОГИ!
Почему структура REGS не содержит просто массив?
@Chris, потому что это аппаратные регистры, это разные регистры с разными именами ...
Имена не имеют значения. Они расположены последовательно, без промежутков, одинакового размера? Я правильно понимаю, что речь идет о регистрах с отображением памяти? Я привык к этому во встроенных средах. Приведите несколько примеров доступа к ним; потому что показанный код не обращается к оборудованию.
Что typedef struct TILE {} TILE; должно быть? Это недопустимый C и не имеет никакого смысла.





Макросы — неправильное решение, и они существуют только во время компиляции, поэтому вы не можете использовать их вместе со значениями во время выполнения.
Стандартный способ создания типа, в котором вы можете получить доступ к элементам по отдельным именам или в виде массива, заключается в использовании union:
typedef union {
struct // anonymous struct, must be compiled with a standard C compiler
{
TILE tile00, tile01, tile02,
tile10, tile11, tile12,
tile20, tile21, tile22;
};
TILE tile [3][3];
} REGS;
Теперь вы можете использовать отдельные имена:
regs.tile00 = tiles[0][0];
regs.tile01 = tiles[0][1];
Или тип массива:
for(size_t i=0; i<3; i++)
{
for(size_t j=0; j<3; j++)
{
regs.tile[i][j] = tiles[i][j];
}
}
(Однако помните о выравнивании/заполнении структуры, так как есть некоторые особые случаи, когда это может привести к каламбуру типа объединения.)
И просто для полноты картины, НАСТОЯТЕЛЬНО НЕ РЕКОМЕНДУЕМАЯ версия, в которой используются макросы: godbolt.org/z/rP5jf7W99. И это зависит от списка констант, которые жестко запрограммированы.
Препроцессор Си так не работает. Ваш
MACRO_LOOPбудет заменен только один раз во время компиляции. Вы можете попытаться поместитьREGS regsвunion, который содержит массив помимо содержимогоREGS.