Как увеличить значение при инициализации структуры?

Инициализация структуры с помощью unsigned short id с помощью #define...


static unsigned short mId = 0;

typedef struct
{
    /* data */
    unsigned short id;
    const char *name;
    bool enabled;
} Machine;

#define CREATE_MACHINE(_mName_) Machine m##_mName_ = {mId++, #_mName_, false};

Как я могу увеличить mId для следующей инициализации экземпляра? mId++ не допускается в инициализаторе.

Итак, я также попробовал использовать функцию, как было предложено в одном комментарии:

static Machine _create_machine(const char *name)
{
    unsigned short id = mId++;
    Machine m = {id, name, false};

    return m;
}

// corrected typo in method parameter
#define CREATE_MACHINE(_mName_) Machine m##_mName_ = _create_machine(#_mName_);

Невозможно использовать функцию в постоянном выражении.

Полный исходник по запросу...

// main.c
#include <stdio.h>
#include <stdbool.h>

#include "../include/machine.h"

MAKE_MACHINE(test)

int main()
{
    PLACE(mtest);
    printf("placed machine[%d] enabled: %s\n", mtest.id, B(mtest.enabled);

    DROP(mtest);
    printf("dropped machine[%d] enabled: %s\n", mtest.id, B(mtest.enabled);
}

// machine.h
#ifndef MACHINE_H
#define MACHINE_H

#include "op/data_types.h"

static USHORT mId = 0;

enum MachineState
{
    M_IDLE,
    M_RUN,
    M_LOCK
};

typedef struct
{
    /* data */
    const USHORT id;
    const CHAR *name;
    BOOL enabled;
} Machine;

static Machine _make_machine(const char *name)
{
    USHORT id = mId++;
    Machine m = {id, name, false};

    return m;
}

static void _place_machine(Machine *machine)
{
    machine->enabled = true;
}
static void _drop_machine(Machine *machine)
{
    machine->enabled = false;
}

#define MAKE_MACHINE(_mName_) Machine m##_mName_ = _make_machine(#_mName_);

#define PLACE(_machine_) _place_machine(&_machine_);
#define DROP(_machine_) _drop_machine(&_machine_);

#endif //  MACHINE_H

Использовать функцию? В любом случае он вам понадобится, если вы собираетесь создать Machine в нескольких потоках одновременно.

Stephen Newell 08.07.2024 02:58

Я попробовал использовать функцию, и ей тоже не понравилось использование функции, потому что это постоянное значение...??? Вот на что жаловалась IDE. Я добавлю это как то, что я пробовал.

IAbstract 08.07.2024 02:59

Зачем пытаться сделать это с помощью макроса с динамически определяемым именем переменной, содержащим последовательные номера? Почему бы просто не сохранить их в массиве?

user229044 08.07.2024 03:00

Вы пытаетесь использовать этот макрос для создания экземпляров области файлов? Это объясняет, почему mId++ вызывает у вас проблемы.

dbush 08.07.2024 03:03

@user229044 user229044 Потому что в структуре есть id, который необходимо назначать постепенно.

IAbstract 08.07.2024 03:03

@dbush: да... в этом и цель. Я следую некоторым методам, с которыми недавно столкнулся, и изучаю ограничения, преимущества, плюсы и минусы. Но, по крайней мере, теперь я знаю, почему это не работает. Но хотелось бы найти решение (если оно есть).

IAbstract 08.07.2024 03:04

Как вы компилируете версию функции? Для меня это компилируется чисто (gcc m.c -Wall -Wextra -o m).

Stephen Newell 08.07.2024 03:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Функция будет работать. Полный рабочий пример:

#include <stdio.h>
#include <stdbool.h>

static unsigned short mId = 0;

typedef struct
{
    /* data */
    unsigned short id;
    const char *name;
    bool enabled;
} Machine;

static Machine make_machine(const char * name) {
    // lock mutexes, atomic operations, etc.
    unsigned short next_id = mId++;
    // unlock mutexes if necessary
    Machine ret = {next_id, name, false};
    return ret;
}

#define CREATE_MACHINE(_mName_) Machine m##_mName_ = make_machine(#_mName_)

int main() {
    CREATE_MACHINE(hello);
    CREATE_MACHINE(world);
    printf("%u: %s\n", mhello.id, mhello.name);
    printf("%u: %s\n", mworld.id, mworld.name);
    return 0;
}

Поскольку функция не ограничена таким же образом, мы можем выполнять дополнительную работу, например приращение mId. Если вы хотите использовать разные увеличивающиеся переменные идентификатора, make_machine может взять unsigned short*, которым он манипулирует внутри самой функции, и который все равно может быть скрыт макросом.

Итак, вот как правильно инициализировать значение области файла. Если бы я действительно хотел создать эти константы, как бы я это сделал? Я неправильно понял, о чем говорилось в комментариях к сообщению относительно области действия файла.

IAbstract 08.07.2024 03:21

Вы хотите, чтобы созданное Machine было const? Вам просто нужно добавить const к типу в макросе (const Machine m##_mName_ = ...).

Stephen Newell 08.07.2024 03:23

ну, я думаю, я имел в виду глобальную область действия, а не файловую. IDE жаловалась, что функцию нельзя использовать в константном выражении, так что я думаю, это не const. Все еще разбираюсь в понятиях. Хотя я понимаю. Цените помощь.

IAbstract 08.07.2024 03:36

Если вы отредактируете свой вопрос, чтобы полностью показать свою первоначальную попытку и то, что не работает, я поиграю с этим и посмотрю, что смогу сделать. Ничего страшного, если он не скомпилируется, но это проще, чем гадать, как выглядит ваш код.

Stephen Newell 08.07.2024 03:45

@StephenNewell Использование любого макроса в области файла не работает, поскольку инициализатор содержит выражение, которое не является постоянным выражением.

dbush 08.07.2024 03:47

Я использую немного другой подход. Этот ответ наиболее полезен для понимания ограничений моего подхода.

IAbstract 09.07.2024 15:17

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

При этом вполне возможно сделать все это во время компиляции. Я бы внедрил шаблон проектирования «X-макросы» и поместил все имена в список:

#define MACHINE_NAMES(X) \
  X(Bob)                 \
  X(Bill)                \

Затем мы можем сгенерировать перечисление на основе этого:

typedef enum
{
  #define MACHINE_ENUM(name) MACHINE_##name,
  MACHINE_NAMES(MACHINE_ENUM)
} machine_enum_t;

Все объявления переменных тогда станут:

#define CREATE_MACHINE(name) Machine m##name = {MACHINE_##name, #name, false};
MACHINE_NAMES(CREATE_MACHINE)

После предварительной обработки вы теперь сидите на чем-то вроде:

Machine mBob  = {MACHINE_Bob,  "Bob",  false};
Machine mBill = {MACHINE_Bill, "Bill", false};

Где MACHINE_Bob == 0, MACHINE_Bill == 1 и так далее. Однако вам, вероятно, следует сделать это массивом - где MACHINE_##name дает вам индекс массива.

Если я правильно понимаю этот подход, мне нужно знать все машины заранее. Это верно?

IAbstract 09.07.2024 15:15

@IAbstract Да, это требование для всего, что разрешается во время компиляции.

Lundin 09.07.2024 15:17

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