C++ structure initialization with all zeros - c++

In C++ if I initialize the structure in the form of "= {}", as in example below, does it ensure to assign values zero to all the member of the structure?
I understand this seem duplicate question, But my question also is if it initializes zero to all members, does it also apply for complex structure ?
Like structure within structure , or for this each member has to be explicitly assigned value zero in the code?.
typedef struct s{
int i;
bool x;
};
int main ()
{
s initial = {};
printf("%d %d", initial.i, initial.x);
}
Edit: To reference complex structure,
typedef struct scomplex{
s initial;
s t[5];
};
int main (void)
{
scomplex sc = {};
printf ("%d %d %d",sc.initial.i, sc.initial.x, sc.t[0].i);
}

But my question also is if it initializes zero to all members, does it also apply for complex structure ?
Yes, all members will be initialized, including "complex" member, but might not be initialized to zero, the final effect is determined by their types.
According to your sample code, struct s is an aggregate type, then aggregate initialization is performed.
(emphasis mine)
If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates).
For this case the member i and x of struct s will be value initialized to zero.
4) otherwise, the object is zero-initialized.
If struct s has any other members, they'll be initialized (value initialized or aggregate initialized according to their types) by empty lists recursively.
EDIT
For your added sample (struct scomplex), the member initial will be value initialized, and the final effect depends on the type s. And another member is an array, which will be aggregate initialized with empty list, and all the elements of the array will be value initialized; Same as member initial, the effect depends on the type s.

Problem
Will this initialize all of the members to 0?
typedef struct s{
int i;
bool x;
};
int main ()
{
s initial = {};
printf("%d %d", initial.i, initial.x);
}
Answer: yes. Proof? Here you can see it become 0.
Better Alternatives?
This is an opinionated section. But In My Opinion (IMO), initializing it with {0} would be more readable than {}, as it notifies the user of the 0. It is actually being filled up with 0's.
s initial = {0};
What is this called?
This is called Aggregate Initialization, as Dieter Lücking defined, or Value Initialization, as songyuanyao noted. It's basically a form of initialization where you can initialize a struct with values you would like. For example, let's initialize it with the value 1 instead of 0! You would do:
// Example program
#include <stdio.h>
#include <iostream>
typedef struct s{
int i;
bool x;
};
int main ()
{
s initial = {1,1};
printf("%d %d", initial.i, initial.x);
}
You can see this compiled here. As you can see above, I am doing 1,1 which is normal initialization. As opposed to 0 initialization, you can't just initialize all the parts of the struct as easily as you can with 0.
References
cpprefrence
what is aggregate initialization
What do the following phrases mean in C++: zero-, default- and value-initialization?
Glossary
Aggregate Initialization :
Aggregate initialization is a form of list-initialization, which initializes aggregates.
Value Initialization:
Initialize values
This is the initialization performed when a variable is constructed with an empty initializer.

Related

Initialize a std::vector of structures to zero

I am guaranteed to initialize a vector of struct with each element initialized to zero with that code ?
#include <vector>
struct A {
int a, b;
float f;
};
int main()
{
// 100 A's initialized to zero (a=0, b=0, f=0.0)
// std::vector<A> my_vector(100, {}); does not compile
std::vector<A> my_vector(100, A{});
}
Short answer : Yes
To know how refer below :
when you write
std::vector<A> my_vector(...)
you are doing value initialization if the parentheses are empty, or direct initialization if non-empty.
and when you write A{} you are doing list initialization which implies value initialization if the braces are empty, or aggregate initialization if the initialized object is an aggregate.
as your parentheses are non-empty so below code
std::vector<A> my_vector(100, A{});
is interpreted as
std::vector<A> my_vector(/*created vector of 100 elements */ 100, /* by list Initialization of struct with default values*/A{});
As A{} is empty in this case you are doing value initialization which is leading to zero_initialization
as
As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.
Yes it is guaranteed since A{} is value initialization and from cppreference:
Zero initialization is performed in the following situations:
As part of value-initialization sequence for non-class types and for members of value-initialized class types that have no constructors, including value initialization of elements of aggregates for which no initializers are provided.
You can also use:
std::vector<A> my_vector(100, {0,0,0});
Yes, you are guaranteed to have zero initialization with that code

Returning inline defined structure with uninitialised member. C++

This questions received too little attention in forums.
It has been asked before but no one captured this little detail. As a result I am not sure if I am doing the right thing:
Simple example:
struct TEST {
bool a;
int b;
};
TEST func() {
return { false };
}
Is this correct? Note that int value is not initialized.
While it would not be a problem to just set it to 0, more problems arise:
struct _FILE_MUTEX {
bool locked;
HANDLE handle;
};
And the last member of the structure could become more and more complex from vector,arrays to function pointers.
Can I leave some of the members empty when returning an inline-initialised structure?
This is called aggregate initialization.
https://en.cppreference.com/w/cpp/language/aggregate_initialization
If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
Thus, in aggregate initialization you allowed to provide less clauses than members in structure. Every remaining member (e.g. X), that doesn't have default initializer, would be initialized as X{}.

Initializing a C++ Structure

Is there a difference between initializing a structure these two ways:
structVar = {}
and
structVar = {0}
It really depends on the nature of the struct.
If it is an aggregate, the two are largely equivalent. However, the first one is general in that it simply value-initializes the struct. The second one requires that the struct's first member be initializable with 0, and initializes the rest of elements as if they were each initialized by an empty initializer {}, in other words,
structVar = {0, {}, {}, {}, ..... };
so each remaining element is value-initialized.
If it is not an aggregate, then it depends on what constructors, if any, have been provided. There simply isn't enough information to say.
corrected
If the structure is an aggregate, the 2 definitions perform the same thing. From the C++11 standard (N3337):
8.5.1/7 If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from its brace-or-equal-initializer or, if there is no brace-or-equal- initializer, from an empty initializer list (8.5.4).
If the structure contains two members, like
struct S
{
int x;
double y;
};
then structVar = {} will value-initialize the members, i.e. they will become zero (or if the members are non-PODs, the default ctor will be called).
The line structVar = {0} will initialize only the first member of the struct with zero. Since in this case you have an aggregate, the rest of the members are value-initialized by empty lists, so effectively you have
structVar = {0, {} };
C++14 added the possibility of aggregate initialization for aggregates containing brace-or-equal initialized members, i.e.
struct S
{
int x;
double y{1.1}; // or double y = 1.1;
}
In this case,
structVar = {0};
initializes x with 0 and y with 1.1. This was not possible before C++14.
PS: just tested the code above, clang++ compiles it with -std=c++1y, however g++ 4.9.2 rejects it even if I compile with -std=c++14.

C and C++ : Partial initialization of automatic structure

For example, if somestruct has three integer members, I had always thought that it was OK to do this in C (or C++) function:
somestruct s = {123,};
The first member would be initialized to 123 and the last two would be initialized to 0. I often do the same thing with automatic arrays, writing int arr[100] = {0,}; so that all integers in an array are initialized to zero.
Recently I read in the GNU C Reference Manual that:
If you do not initialize a structure variable, the effect depends on
whether it is has static storage (see Storage Class Specifiers) or
not. If it is, members with integral types are initialized with 0 and
pointer members are initialized to NULL; otherwise, the value of the
structure's members is indeterminate.
Can someone please tell me what the C and C++ standards say regarding partial automatic structure and automatic array initialization? I do the above code in Visual Studio without a problem but I want to be compatible with gcc/g++, and maybe other compilers as well. Thanks
The linked gcc documentation does not talk of Partial Initialization it just talks of (Complete)Initialization or No Initialization.
What is partial Initialization?
The standards do not define Partial initialization of objects, either there is Complete initialization or No-initialization. Partial Initialization is a non-standard terminology which commonly refers a situation where you provide some initializers but not all i.e: Fewer initializers than the size of the array or the number of structure elements being initialized.
Example:
int array[10] = {1,2}; //Case 1:Partial Initialization
What is (Complete)Initialization or No Initialization?
Initialization means providing some initial value to the variable being created at the same time when it is being created. ie: in the same code statement.
Example:
int array[10] = {0,1,2,3,4,5,6,7,8,9}; //Case 2:Complete Initialization
int array[10]; //Case 3:No Initialization
The quoted paragraph describes the behavior for Case 3.
The rules regarding Partial Initialization(Case 1) are well defined by the standard and these rules do not depend on the storage type of the variable being initialized.
AFAIK, All mainstream compilers have 100% compliance to these rules.
Can someone please tell me what the C and C++ standards say regarding partial automatic structure and automatic array initialization?
The C and C++ standards guarantee that even if an integer array is located on automatic storage and if there are fewer initializers in a brace-enclosed list then the uninitialized elements must be initialized to 0.
C99 Standard 6.7.8.21
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.
In C++ the rules are stated with a little difference.
C++03 Standard 8.5.1 Aggregates
Para 7:
If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5).
[Example:
struct S { int a; char* b; int c; };
S ss = { 1, "asdf" };
initializes ss.a with 1, ss.b with "asdf", and ss.c with the value of an expression of the form int(), that is,0. ]
While Value Initialization is defined in,
C++03 8.5 Initializers
Para 5:
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible
default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static
data member and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized
In C, objects are never partially initialised - if any part of them is initialised, the entire object (and all sub-objects recursively) are initialised. If no explicit initialiser is provided then elements are initialised to "zero of the appropriate type".
The quote in your question is referring to when the initialiser for the entire object is completely left out, not when a sub-object lacks an initialiser. For example, assuming that arr has automatic storage duration, then this:
int arr[100] = { 123 };
initialises arr[0] to 123 and every other element of arr to 0. Whereas this:
int arr[100];
leaves every element of arr uninitialised. It is this latter case that the quote is in reference to.
newest gcc versions also allow to "partially" initialize and zeromem at the same time:
typedef struct{
int a,b,c;
}T;
T s = {0, .b=5};
the struct members now will have these values: a=0, b=5, c=0
i don't have any info on whether other compilers allow this or not :p

Aggregate Initialization Safety in C++

Suppose I have the following struct:
struct sampleData
{
int x;
int y;
};
And when used, I want to initialize variables of sampleData type to a known state.
sampleData sample = { 1, 2 }
Later, I decide that I need additional data stored in my sampleData struct, as follows:
struct sampleData
{
int x;
int y;
int z;
};
It is my understanding that the two field initialization left over from my pre-z data structure is still a valid statement, and will be compiled., populating the missing fields with default values.
Is this understanding correct? I have been working recently in Ada, which also allows aggregate initialization, but which would flag a similar issue as a compilation error. Assuming that my assumptions about the C++ code above are correct, is there a language construct which would recognize missing initialization values as an error?
Initialising variables that way is only supported with Aggregate Classes.
If you add constructor(s) then then problem goes away, but you'll need to change the syntax a little and you lose the ability to store the struct in a union (among other things).
struct sampleData
{
sampleData(int x, int y) : x(x), y(y) {}
int x;
int y;
};
sampleData sample( 1, 2 );
Adding z (and changing the constructor) will mark sample( 1, 2 ) as a compile error.
Yes, any elements you leave off of the initialization list will be initialized to zero (for POD scalar types) or using their default constructor (for classes).
The relevant language from the C standard is quoted here:
[6.7.8.21] 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 am sure someone more motivated than I could find the corresponding language in one of the C++ specs...
Note that this implies that POD scalar elements are initialized as if you wrote "= 0". Which means it will correctly initialize pointers to NULL and floats to 0.0 even if their representations do not happen to be all-zero bytes. It also implies that it works recursively; if your struct contains a struct, the inner struct will be properly initialized as well.
As a followup to Nemo's answer with the C standardese, here is what the C++03 standard says:
§8.5.1/7:
If there are fewer initializers in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized.
§8.5/5:
To value-initialize an object of type T means:
if T is a class type with a user-declared constructor, then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized
To zero-initialize an object of type T means:
if T is a scalar type, the object is set to the value of 0 (zero) converted to T;
if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;
if T is a union type, the object’s first named data member) is zero-initialized;
if T is an array type, each element is zero-initialized;
if T is a reference type, no initialization is performed.
Why not use
sampleData sample = { x: 1, y:2 } ;
?
But you'd still run into the problem of z being initialized to an unpredictable value, so it's better to define a constructor which sets all variables to well defined values.