Как перебрать имена переменных?

Мне нужно сделать некоторые назначения следующим образом.

В структуре 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);
    }
}

но он не компилируется.

ПОЖАЛУЙСТА ПОМОГИ!

Препроцессор Си так не работает. Ваш MACRO_LOOP будет заменен только один раз во время компиляции. Вы можете попытаться поместить REGS regs в union, который содержит массив помимо содержимого REGS.

Gerhardh 11.01.2023 07:31

Почему структура REGS не содержит просто массив?

Chris 11.01.2023 08:05

@Chris, потому что это аппаратные регистры, это разные регистры с разными именами ...

Xingx1 11.01.2023 08:08

Имена не имеют значения. Они расположены последовательно, без промежутков, одинакового размера? Я правильно понимаю, что речь идет о регистрах с отображением памяти? Я привык к этому во встроенных средах. Приведите несколько примеров доступа к ним; потому что показанный код не обращается к оборудованию.

Yunnosch 11.01.2023 09:24

Что typedef struct TILE {} TILE; должно быть? Это недопустимый C и не имеет никакого смысла.

Lundin 11.01.2023 11:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Макросы — неправильное решение, и они существуют только во время компиляции, поэтому вы не можете использовать их вместе со значениями во время выполнения.

Стандартный способ создания типа, в котором вы можете получить доступ к элементам по отдельным именам или в виде массива, заключается в использовании 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. И это зависит от списка констант, которые жестко запрограммированы.

Lundin 11.01.2023 11:54

Другие вопросы по теме