[SOLVED] initiation of struct

Hi,
Read an article (C: Structure Initialization (Advanced) | Programming in Linux) about how to initiate a struct in C. However, it doesn't seem to compile.

Example

struct Error {
  byte code;
  boolean active;
  char msg[21];
};

struct ErrorStates {
  Error ERR_A;
  Error ERR_B;
  // ... and so on
};

// I thought I could do this. But it wont compile :(
ErrorStates errors = {
.ERR_A = {.code=1, .msg="some error"},
.ERR_B = {.code=2, .msg="some other error"},
}

Is there a way to init the struct using the name of the fields (for the sake of code clairty)?

Show the exact compiler error messages please.

Yes, good ide... Missed that. Here is what the compiler says

sketch_sep15a:14: error: expected primary-expression before '.' token
sketch_sep15a:14: error: expected primary-expression before '{' token
sketch_sep15a:14: error: expected `}' before '{' token
sketch_sep15a:14: error: expected ',' or ';' before '{' token
sketch_sep15a:14: error: expected unqualified-id before ',' token
sketch_sep15a:15: error: expected unqualified-id before '.' token
sketch_sep15a:15: error: expected unqualified-id before ',' token
sketch_sep15a:16: error: expected unqualified-id before '}' token
sketch_sep15a:16: error: expected declaration before '}' token

// I thought I could do this. But it wont compile :frowning:

I don't know why you thought you could do that. The compiler knows what variables in the structure to store the data in. It doesn't need your help to figure that out.

ErrorStates errors = {
   { 1, "some error" },
   { 2, "some other error" },
}

Of course, this won't compile either, since you are not supplying all the initializers for the structure members, but you can work out what you want the missing values to be and supply them.

I thought I could do it because that's what's done in mentioned article. However that is for C and perhaps C++ is different?

Although I define Error like below my example won't compile.

struct Error {
  byte code;
  //boolean active;
  char msg[21];
};

I know I could just list the values, but then I need to know in what order they shall appear - and that is exactly what I want to avoid. Supplying the name of the fields just makes the code easier to read and there's no risk to mix things up. My example here is very simple but the case is of course general.

Should I conclude there is no way to init a struct using its field names?

I know I could just list the values, but then I need to know in what order they shall appear - and that is exactly what I want to avoid.

There are no shortcuts. You do need to supply the data in the correct order, or write your own code to initialize the members.

Should I conclude there is no way to init a struct using its field names?

The field names must be used when you want to initialize one field at a time, in your code. They are not to be used when you want the compiler to do the initialization for you.

Aha. Well, then I have to live with it. Thanks!

You can do that in C99, the newer version of C. For some silly reason, C++ is no longer a superset of C, and they didn't bother including designated initializers.
It really is a nice feature though.

Correct initialization would be -

struct Error
{
    byte    code;
    boolean active;
    char    msg[21];
};

struct ErrorStates
{
    Error   ERR_A;
    Error   ERR_B;
};

ErrorStates errors =
{
      { 1, false, { "some error" } }
    , { 2, false, { "some other error" } }
};

When initializing arrays C++ will fill unprovided data with the last value you do provide. In this case you're using C character string syntax which automatically provides a trailing zero so the remainder of the array should be initialized with the trailing zero.

Another option, as i think was mentioned is to create an initialiser for the struct:

struct Error
{
    byte    code;
    boolean active;
    char    msg[21];
    Error(byte code_, boolean active_, char* msg_) {
      code = code_;
      active = active_;
      strncpy(msg,msg_,21);
    }
};

Error someError = Error(1,false,"some error");

You could use your errorStates struct like this:

struct ErrorStates {
  Error ERR_A;
  Error ERR_B;
};

ErrorStates states = {someError,Error(2,true,"some other error")}; //just an example

But it would be far easier to use if it were just this (without the second struct):

Error errorSates[] =  {Error(1,false,"some error"),Error(2,true,"some other error")};

Then you could do stuff like this:

Serial.print(errorStates[1].msg); //just for example