Как инициализировать массив структур в другой структуре? - PullRequest
0 голосов
/ 19 октября 2019

У меня есть следующий код, который выдает ошибку компиляции. Он предназначен для анализатора команд для микроконтроллера STM32, написанного на C ++. В основном у меня есть CMD_DEF_ST структура со строкой и указатель на функцию для обработки этой строки. Я добавил еще один указатель на другой массив CMD_DEF_ST в структуре, чтобы иметь возможность обрабатывать параметры команды. Я не могу получить правильную инициализацию, к сожалению. Я не хочу инициализировать его во время выполнения, так как все это должно войти в постоянную флэш-память.

#include <stdio.h>

// **************************
// define command structure
// **************************

// struct forward declaration
typedef struct cmd_def_st CMD_DEF_ST;                       

// typedef for command handler function
typedef void (*CMD_FUNC_HANDLER)(const CMD_DEF_ST* cmddef); 

struct cmd_def_st
{
    const char* cmdstr;          // command string
    const CMD_FUNC_HANDLER func; // pointer to handler
    const CMD_DEF_ST* params;    // pointer to sub parameters
};




// **************************
// declare some commands
// **************************
const CMD_DEF_ST cmd = {"swrst" , [] (const CMD_DEF_ST* cmd) { printf("swrst\n"); },
    NULL};

// **************************
// produces:
// error: braces around scalar initializer for type 'const CMD_DEF_ST* 
//                {aka const cmd_def_st*}'
// **************************
const CMD_DEF_ST cmd2 = { "echo" , [] (const CMD_DEF_ST* cmd) { printf("Error\n"); },
    {
        {"on" , [] (const CMD_DEF_ST* cmd) { printf("Echo on\n"); }, NULL },
        {"off" , [] (const CMD_DEF_ST* cmd) { printf("Echo off\n"); }, NULL },
        NULL
    }
    };

int main()
{
    cmd.func(&cmd); // prints "swrst"

    return 0;
}

Я посмотрел здесь Предупреждение gcc: скобки вокруг скалярного инициализатора и здесь инициализация массива указателей на структуры . Это дало мне несколько идей, чтобы попробовать, но я не мог понять, как заставить это работать для моего собственного кода.

Я попытался изменить определение структуры на:

struct cmd_def_st
{
    const char* cmdstr;          // command string
    const CMD_FUNC_HANDLER func; // pointer to handler
    const CMD_DEF_ST** params;    // pointer to sub parameters
};

с

// **************************
// produces:
// error: taking address of temporary [-fpermissive]|
// error: taking address of temporary [-fpermissive]|
// error: taking address of temporary array|
// **************************
const CMD_DEF_ST cmd2 = { "echo" , [] (const CMD_DEF_ST* cmd) { printf("Error\n"); },
    (const CMD_DEF_ST* []){
        &(const CMD_DEF_ST){"on" , [] (const CMD_DEF_ST* cmd) { printf("Echo on\n"); }, NULL },
        &(const CMD_DEF_ST){"off" , [] (const CMD_DEF_ST* cmd) { printf("Echo off\n"); }, NULL },
        NULL
    }
    };

но я все еще получил ошибку компиляции.

Может кто-нибудь сказать мне, как правильно инициализировать cmd2, или кто-то знает хороший способ сделать это?

Ответы [ 2 ]

1 голос
/ 19 октября 2019

если в структуре cmd_def_st вы используете const CMD_DEF_ST* params;, вы пытаетесь инициализировать скалярный тип (указатель) с массивом структур. Так что здесь вам действительно нужен адрес типа CMD_DEF_ST (как это предлагается в ответе супер).

Во втором случае вы пытаетесь получить адрес rvalue, временного объекта, который перестанет существовать послетекущий оператор, поэтому вы получаете сообщение об ошибке.

, если вас не устраивает эта двухэтапная инициализация, я мог бы предложить создать структуры как для cmds, так и для subcmds, чтобы обеспечить полноту типов для массива params в cmd_def_st:

struct subcmd_def_st
{
    const char* cmdstr;          // command string
    const CMD_FUNC_HANDLER func; // pointer to handler
//    const SUBCMD_DEF_ST params;     // assuming no sub-subcmds
};

struct cmd_def_st
{
    const char* cmdstr;          // command string
    const CMD_FUNC_HANDLER func; // pointer to handler
    const subcmd_def_st params[];     // pointer to sub parameters
};

const CMD_DEF_ST cmd2 =
    { 
        "echo" , 
        [] (const CMD_DEF_ST* cmd) { printf("Error\n"); },
        {
            { "on" , [] (const CMD_DEF_ST* cmd) { printf("Echo on\n"); } },
            { "off" , [] (const CMD_DEF_ST* cmd) { printf("Echo off\n"); } },
            { NULL }
        }
    };
1 голос
/ 19 октября 2019

Я не знаю, можно ли это сделать так, как вы пытаетесь, но разделить инициализацию на две работы. Сначала массив подкоманд, сопровождаемый командой и просто передающий указатель.

const CMD_DEF_ST subcmd1[] = {{"on" , [] (const CMD_DEF_ST* cmd) { printf("Echo on\n"); }, NULL }, {"off" , [] (const CMD_DEF_ST* cmd) { printf("Echo off\n"); }, NULL }};
const CMD_DEF_ST cmd2 = { "echo" , [] (const CMD_DEF_ST* cmd) { printf("Error\n"); }, subcmd1};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...