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:
Usage of double braces
{{ }}
does not change the layout of data in memoryThis 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
What's the Semantically Accurate Position for the Ampersand in C++ References
Set the Digits After Decimal Point
Stl Vectors with Uninitialized Storage
String Comparison with the Most Similar String
C++: Function Pointer to Functions with Variable Number of Arguments
Why Are iOStreams Not Copyable
C++ Copy Constructor Gets Called Instead of Initializer_List<>
Why Are C++ Int and Long Types Both 4 Bytes
How to Call a Cmake Function from Add_Custom_Target/Command
Speed Accessing a Std::Vector by Iterator VS by Operator[]/Index
Cmake Imported Library Behaviour