How to initialise a struct in arduino.

Hello to all members. Happy new year to you !

I have a project where i want to create a struct. I was wondering if i am initialising my struct corectly.

Here is the code fragment:

struct Indata
{
   byte info1 = 0;
   unsigned long Time = 0;
   char rcvdinfo [10] = {};
   bool DataOK = true;
};

struct Indata Input1, Input2;


void setup
{
  code...
}


void loop
{
  code...
}

The IDE seems to accept that but still im not sure.

That looks OK. You can always check by printing the values of the members of the struct. If the data is not to be initialised immediately then you can omit the explicit values as you can with any other variable and populate them later by using the explicit names of the members

iv'e updated post#1. Thank you sir !

For future google searches, it may be useful to know that Arduino uses a standard C++ compiler1.
So the techniques you find for “How to initialize a struct in C++” will also be valid in an Arduino sketch.

Pieter


(1): On AVR (Arduino UNO, Nano, Mega etc.), you don’t have access to the C++ Standard Template Library (STL), but the compiler is still just a GCC C++ compiler.

Thank you for your response pieter.
The problem is that i have limited knowledge of C and no knowledge of C++.
I am planning to try to learn C++ via online lessons soon though.

HellasT:
iv'e updated post#1. Thank you sir !

It is regarded as impolite to update a post that has been commented on as it can make a nonsense of the comment

I apologise for that. i begun editting the text before i received your relpy. It probably took me long enough . Im sorry. I will avoid that in the future.

UKHeliBob:
It is regarded as impolite to update a post that has been commented on as it can make a nonsense of the comment

Ive restored post#1 to its original state.

Is this way correct and acceptable ?

struct Indata
{
   byte info1;
   unsigned long Time0;
   char rcvdinfo [10];
   bool DataOK;
};

struct Indata Input1, Input2 = {0,0,{},false};


void setup
{
  code...
}

void loop
{
  code...
}

Thank you !

That looks OK (and thank you for restoring the original post.) It only initializes Input2, though.
You might want to look into typedef as well.

Note that global structures will be initialized to all zeros by default - you only need to provide initialization if you want the contents to be non-zero.

You don’t need the struct keyword for the declaration of Input1 and Input2. (It’s a remnant from C, Arduino uses C++.)

struct Indata
{
   byte info1;
   unsigned long Time0;
   char rcvdinfo [10];
   bool DataOK;
};

Indata Input1, Input2 = {0,0,{},false};

As previously pointed out, be careful when you initialise the 2 structs as

Indata Input1, Input2 = {0,0,{},false};

will not initialise Input1, although in this case nothing will change in Input2 either. That may not matter but you ought to be aware of it

UKHeliBob:
That looks OK.

What does C/C++ standard say about initializing the members of a struct? Should they not be initialized outside the struct like?:

void setup()
{
  Serial.begin(9600);
  Input1.info1 = 10;
  Input2 = {0, 0, {}, false};
  Serial.print(Input1.info1);
}

GolamMostafa:
What does C/C++ standard say about initializing the members of a struct? Should they not be initialized outside the struct like?:

void setup()

{
  Serial.begin(9600);
  Input1.info1 = 10;
  Input2 = {0, 0, {}, false};
  Serial.print(Input1.info1);
}

Why would you think that? The code he posted was fine.

https://en.cppreference.com/w/c/language/struct_initialization
https://en.cppreference.com/w/cpp/language/aggregate_initialization

PieterP:
Why would you think that? The code he posted was fine.

It is good; because it works.
It is good; because, it works as per language standard.

Which one of the above two statements is acceptable?

In the reply of Post#1 of @UKHeliBob, we find this: "If the data is not to be initialised immediately then you can omit the explicit values as you can with any other variable and populate them later by using the explicit names of the members." That means according to @UKHeliBob, members of the struct could be initialized in either of two ways.

My query is: which one is the standard.

GolamMostafa:
It is good; because it works.
It is good; because, it works as per language standard.

Which one of the above two statements is acceptable?

In the reply of Post#1 of @UKHeliBob, we find this: “If the data is not to be initialised immediately then you can omit the explicit values as you can with any other variable and populate them later by using the explicit names of the members.” That means according to @UKHeliBob, members of the struct could be initialized in either of two ways.

My query is: which one is the standard.

There is no standard way. The standard allows for multiple ways. I suggest you read the relevant pages on cppreference (see previous post) if you want to know all the details.

GolamMostafa:
What does C/C++ standard say about initializing the members of a struct? Should they not be initialized outside the struct like?:

void setup()

{
  Serial.begin(9600);
  Input1.info1 = 10;
  Input2 = {0, 0, {}, false};
  Serial.print(Input1.info1);
}

Beside, this is not an initialization. This will invoke a default constructor and a default copy assignment.

arduino_new:
Beside, this is not an initialization.

It is an initialization; because, setup() function gets executed only once.

GolamMostafa:
It is an initialization; because, setup() function gets executed only once.

Hmm, I should have been more precise,

Input2 = {0, 0, {}, false};

This is not an initialization. This will invoke a default constructor and a default copy assignment.

arduino_new:
Hmm, I should have been more precise,

Input2 = {0, 0, {}, false};

This is not an initialization. This will invoke a default constructor and a default copy assignment.

It is initialization. Copy elision will take place, no default constructor is called.

// g++ copy-elision.cpp -std=c++11 && ./a.out

#include <cstdio>

struct S {
    S() { puts(__PRETTY_FUNCTION__); }
    S(int i) : i(i) { puts(__PRETTY_FUNCTION__); }
    S(const S &) { puts(__PRETTY_FUNCTION__); }
    S &operator=(const S &) { puts(__PRETTY_FUNCTION__); return *this; }
    ~S() { puts(__PRETTY_FUNCTION__); }
    int i;
};

S s = {S(S{1})};

int main() {}

Output:

S::S(int)
S::~S()

https://en.cppreference.com/w/cpp/language/copy_elision

Non-mandatory elision of copy/move (since C++11) operations
Under the following circumstances, the compilers are permitted, but not required to omit the copy and move (since C++11) construction of class objects even if the copy/move (since C++11) constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. This is an optimization: even when it takes place and the copy/move (since C++11) constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed:

  • In the initialization of an object, when the source object is a nameless temporary and is of the same class type (ignoring cv-qualification) as the target object. When the nameless temporary is the operand of a return statement, this variant of copy elision is known as RVO, “return value optimization”.
  • […]

Since C++17, it is even mandatory in that case.

GolamMostafa:
It is an initialization; because, setup() function gets executed only once.

Call it what you want, but you were the one asking for details about the standard, and the standard does not call that initialization.

The structs Input1 and Input2 are global variables in your example, and they have static storage duration. If no initializer is provided, it will be zero-initialized before execution of main.

https://en.cppreference.com/w/cpp/language/initialization

Non-local variables
All non-local variables with static storage duration are initialized as part of program startup, before the execution of the main function begins (unless deferred, see below). All non-local variables with thread-local storage duration are initialized as part of thread launch, sequenced-before the execution of the thread function begins. For both of these classes of variables, initialization occurs in two distinct stages:

Static initialization

  • If permitted, Constant initialization takes place first (see Constant initialization for the list of those situations). In practice, constant initialization is usually performed at compile time, and pre-calculated object representations are stored as part of the program image. If the compiler doesn't do that, it still has to guarantee that this initialization happens before any dynamic initialization.
  • For all other non-local static and thread-local variables, Zero initialization takes place. In practice, variables that are going to be zero-initialized are placed in the .bss segment of the program image, which occupies no space on disk, and is zeroed out by the OS when loading the program.

What you're doing in your setup function is assigning new values to the members. This is strictly speaking not initialization.

That being said, while discussing code informally, you will definitely also catch me referring to it as "initialization".