How to Initialize an Array of Struct in C++

Initializing array of structures

There's no "step-by-step" here. When initialization is performed with constant expressions, the process is essentially performed at compile time. Of course, if the array is declared as a local object, it is allocated locally and initialized at run-time, but that can be still thought of as a single-step process that cannot be meaningfully subdivided.

Designated initializers allow you to supply an initializer for a specific member of struct object (or a specific element of an array). All other members get zero-initialized. So, if my_data is declared as

typedef struct my_data {
int a;
const char *name;
double x;
} my_data;

then your

my_data data[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};

is simply a more compact form of

my_data data[4]={
{ 0, "Peter", 0 },
{ 0, "James", 0 },
{ 0, "John", 0 },
{ 0, "Mike", 0 }
};

I hope you know what the latter does.

Initialize an array of structs in C or C99 to all the same values

Quote from C99 standard section 6.7.8:

If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, or fewer characters in a string literal used to initialize an array of known
size than there are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration.

I.e. Only the first element will be initialized to the supplied value while the others will be filled with zeros.

There is no way (in standard C) other than a loop to initialize an array of complex structs (memset() can be used to initialize a block of memory with a specified value).

Quickest way to initialize an array of structures to all-0's?

It the first member of your struct has a scalar type, use

STRUCTA array[MAX] = {{ 0 }};

If the first member of your struct happens to be another struct object, whose first member has scalar type, then you'll have to use

STRUCTA array[MAX] = {{{ 0 }}};

and so on. Basically, you have to open a new level of nested {} every time you "enter" another nested aggregate (a struct or an array). So in this case as long as the first member of each nested aggregate is also an aggregate, you need to go deeper with {}.

All these extra braces are only there to avoid the warning. Of course, this is just a harmless warning (in this specific case). You can use a simple { 0 } and it will work.

Probably the the best way to deal with this is to disable this warning entirely (see @pmg's answer for the right command-line option). Someone working on GCC wasn't thinking clearly. I mean, I understand the value of that warning (and it can indeed be very useful), but breaking the functionality of { 0 } is unacceptable. { 0 } should have been given special treatment.

Initialize values of array in a struct

If the values are the same, you might do something like

struct->array[0] = struct->array[1] = struct->array[2] = struct->array[3] = (unsigned char) something;

Otherwise, if the values are stored in an array, you can use the memcpy function like so

memcpy(struct->array, some_array, sizeof(struct->array));

How could I initialize an array of struct to null?

list[1024]; is array of object of your struct, which you access like

list[j].title;
list[j].year;
list[j].length;

What you are doing is:

list[j]=NULL

list[j] is of type record, NULL is void*. I guess this is not what you have in mind.

Either initialize individual elements in the struct by accessing them individually or use memset as suggested by others.

How to initialize array of structures after declaration in C

Arrays aren't R values, so you can't copy them via assignemnt. But you can use memcpy

#include <string.h>
void init(void)
{
memcpy(&myStruct,(tStruct[]) { {1, 2}, {3, 4}, {5, 6} }, sizeof(myStruct));
}

The code generated by an optimizing compiler shouldn't be much worse than what you'd get with

void init2(void)
{
myStruct[0] = (tStruct){1,2};
myStruct[1] = (tStruct){3,4};
myStruct[2] = (tStruct){5,6};
}

or

void init3(void)
{
myStruct[0].a = 1, myStruct[0].b = 2;
myStruct[1].a = 3, myStruct[1].b = 4;
myStruct[2].a = 5, myStruct[1].b = 6;
}

Gcc and clang are well capable of eliding an unnecessary compound variable like that in favor of assigning individual components directly.

https://gcc.godbolt.org/z/j9f37j

The biggest downside of the memcpy approach is that it's a bit brittle and type-unsafe (and can result in out-of-bounds reads/writes if the unenforced type compatibility is violated).

If your C dialect has __typeof, then with some macro trickery you should be able to almost get around this C language limitation:

#include <string.h>
#define assignAnything(DestPtr,SrcPtr) ((void)((__typeof(SrcPtr)){0} = (__typeof(DestPtr)){0}) /*typecheck*/, memcpy(DestPtr, SrcPtr, sizeof(*(DestPtr))))

/* A Ptr-less version:
#define assignAnything2(Dest,Src) ((void)((__typeof(&(Src))){0} = (__typeof(&(Dest))){0}), memcpy(&(Dest), &(__typeof(Src)){Src}, sizeof(Dest)))
doesn't always work, unfortunately */

int main()
{
int d[3][2][1]={0};
int const s[3][2][1] = {0};
assignAnything(&d,&s); //works
#if NOPE
assignAnything(&s,&d); //will (correctly) compile-time fail because s has more qualifs (const) than d
#endif
}

How to initialize array in an array of structs?

To correctly initialize an array in an array of structures you need to do the following:

typedef struct _TStruct {

uint Values[3];

} TStruct;

TStruct Data[3] = {

{{ 0x86, 0x55, 0x79 }}, {{ 0xaa, 0xbb, 0xcc }}, {{ 0x76, 0x23, 0x24 }}

};

Pay attention to the double braces around every group of values. The additional pair of braces is essential to avoid getting a following gcc error (only when -Wall flag is present, precisely it's "detected" by gcc -Wmissing-braces flag):

warning: missing braces around initializer

Note:

  1. Usage of double braces {{ }} does not change the layout of data in memory

  2. This warning does not appear on MS Visual Studio C++ compiler

See also:

How to repair warning: missing braces around initializer?

GCC Bug 53319

Initializing array of structs in c

Change initialization to:

record list[] = { {1, "one"}, {2, "two"}, {3, "three"} };
/* ^ ^ ^ ^ ^ ^ */

Your initialization with (...) leaves effect similar to {"one", "two", "three"} and creates a struct array with elements { {(int)"one", "two"}, {(int)"three", (char *)0} }

comma operator in C evaluates the expressions from left to right and discard all except the last. This is the reason why 1, 2 and 3 are discarded.

How to initialize an array of structs to a value other than zero like 0xFF?

The sensible way to do this is to find the command in the linker script telling it to back off from touching that memory in the first place. Because why would you want it do be erased only to filled up with 0xFF again? That only causes unnecessary flash wear for nothing.

Something along the lines of this:

.bootloader_data (NOLOAD) :
{
. = ALIGN(512);
*(.bootloader_data *)
} >FLASH

initializing of a struct of whose members are array of another struct

The structure body is an aggregate that contains data members that in turn are aggregates.

You need to write

body r_plate = { { { 0,0 },{ 5,0 },{ 5,1 },{ 0,1 } } };

That is the structure body contains an array so you have to write

body r_plate = { { ... } };

and each element of the array is an object of the structure type. So you will have

body r_plate = { { { 0,0 },{ 5,0 },{ 5,1 },{ 0,1 } } };

The following initializations will be less readable but correct

body r_plate = { { 0,0,5,0,5,1,0,1 } };

and

body r_plate = { 0,0,5,0,5,1,0,1 };

Here is a demonstration program.

#include <iostream>

typedef struct coordinate{
double x;
double y;
}point;

typedef struct sc_cell{ // single cell
point sc[4];
}cell;

typedef struct sb_body { // for single body
point sb[4];
}body;

using namespace std;

int main()
{
body r_plate = { 0,0,5,0,5,1,0,1 };

for ( const auto &p : r_plate.sb )
{
std::cout << "( " << p.x << ", " << p.y << " ) ";
}
std::cout << '\n';

r_plate = { { 0,0,5,0,5,1,0,1 } };

for ( const auto &p : r_plate.sb )
{
std::cout << "( " << p.x << ", " << p.y << " ) ";
}
std::cout << '\n';

r_plate = { { { 0,0 }, { 5,0 } , { 5,1 }, { 0,1 } } };

for ( const auto &p : r_plate.sb )
{
std::cout << "( " << p.x << ", " << p.y << " ) ";
}
std::cout << '\n';

return 0;
}

The program output is

( 0, 0 ) ( 5, 0 ) ( 5, 1 ) ( 0, 1 ) 
( 0, 0 ) ( 5, 0 ) ( 5, 1 ) ( 0, 1 )
( 0, 0 ) ( 5, 0 ) ( 5, 1 ) ( 0, 1 )

As for this assignment

r_plate = { { 0,0 },{ 5,0 },{ 5,1 },{ 0,1 } };

then the first inner brace is considered as starting point of the list-initialization of the array. As the structure has only one data member (the array) then all other list-initializations apart the first one do not have corresponding data members of the structure. So the compiler issues an error.



Related Topics



Leave a reply



Submit