0

I have the following code that produces a compile error. It is for a command parser for a STM32 micro-controller written in C++. Basically I have a CMD_DEF_ST struct with a string and a function pointer to handle that string. I added a further pointer to another CMD_DEF_ST array in the struct, to be able to handle command parameters. I cannot get the initialisation right unfortunately. I do not want to initialize it at runtime, as it all has to go into const FLASH memory.

#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;
}

I had a look here gcc warning: braces around scalar initializer and here initializing array of pointers to structs. It gave me a few ideas to try, but I could not quite figure out how to make it work for my own code.

I tried changing the struct definition to:

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
};

with

// **************************
// 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
    }
    };

but I still got a compile error.

Can someone tell me what is the correct way to initialize cmd2, or does someone know of a good way to do this?

2 Answers 2

1

if in the cmd_def_st struct you use const CMD_DEF_ST* params; you are trying to initialize a scalar type (pointer) with array of structs. So here you actually need an address of CMD_DEF_ST type (like it is suggested in the super's answer).

In your second case you are trying to take an address of rvalue, a temporary object that will cease to exist after the current statement, so you are receiving an error.

if you are not happy with that two-step initialization I might suggest making structs both for cmds and subcmds to provide type completeness for the params array in the 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 }
        }
    };
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I tried this but then I run into this stackoverflow.com/questions/21152171/… problem,
I tried to compile this code on g++ 5 and really that initialization problem appeared, but after upgrade to g++ 7 it was compiled with no errors (also with std=c++11 option)
Thank you. I was on GCC 5. So as you correctly say building this with GCC 7 does exactly what I wanted. Thank you very much. I have changed to this as the accepted solution.
1

I don't know if it can be done in the way you are trying, but splitting the initialization in two works. First the array of sub-commands followed by the command and just passing in the pointer.

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};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.