Regarding 2-d array initialisation in C++ - c++

I get mixed responses for this question on 2-d array initialization in C++.
Here's the scenario:
class MyClass {
private:
static char my2dArray[10][20];
};
char MyClass::my2dArray[10][20] = {{0}};
Now does this initialize all elements of this array with 0?
Also, if I have the following type definition:
typedef unsigned char u8;
and this array is static u8 my2dArray[10][20], will the same initialization work?
Assuming it's mandatory that all elements are explicitly initialized to 0.

Now does this initialize all elements of this array with 0?
Yes
If the initializer list does not have the same number of elements as the actual array. Then the array is zero filled.
will the same initialization work?
Yes
The same processes is at work here.

class MyClass {
private:
static char my2dArray[10][20];
};
char MyClass::my2dArray[10][20] = {{0}};
Now does this initialize all elements of this array with 0?
Sort of.
Recall that the elements of your array are not char, but char[10] (which cannot be 0).
What you're doing here is initialising the outer array by providing an initialiser for the first inner array ({0}, again setting only the inner array's first element to 0).
You're then letting the "default", implicit initialization behaviour take over for the subsequent elements in both arrays.
[n3290: 8.5.1/1]: An aggregate is an array or a class (Clause 9)
with no user-provided constructors (12.1), no
brace-or-equal-initializers for non-static data members (9.2), no
private or protected non-static data members (Clause 11), no base
classes (Clause 10), and no virtual functions.
[n3290: 8.5.1/2]: When an aggregate is initialized by an initializer
list, as specified in 8.5.4, the elements of the initializer list are
taken as initializers for the members of the aggregate, in increasing
subscript or member order. Each member is copy-initialized from the
corresponding initializer-clause. If the initializer-clause is an
expression and a narrowing conversion (8.5.4) is required to convert
the expression, the program is ill-formed. [ Note: If an
initializer-clause is itself an initializer list, the member is
list-initialized, which will result in a recursive application of the
rules in this section if the member is an aggregate. —end note ]
[n3290: 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 an empty initializer
list (8.5.4).
[n3290: 8.5.4/3:] [..] Otherwise, if the initializer list has no
elements, the object is value-initialized. [..]
The [final draft] standard actually contains a non-normative example of a similar behaviour:
[n3290: 8.5.1/10]: [..] [ Example: [..] On the other hand,
float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } };
initializes the first column of y (regarded as a two-dimensional
array) and leaves the rest zero. —end example ]
So, ultimately, yes. All of your innermost array elements will hold the value 0; it's just that your {{0}} didn't actually do very much to make that happen.
Assuming it's mandatory that all elements are explicitly initialized to 0.
Well, since your array has static storage duration, its memory will be zero-initialised anyway, so this is ultimately pointless to bother concerning yourself over.
Also, if I have the following type definition:
typedef unsigned char u8;
and this array is static u8 my2dArray[10][20], will the same initialization work?
Yes. The type alias doesn't change anything: this array has precisely the same type (and storage duration) as the first one, and the same rules apply.

Related

2D array of pointers c++ with null pointers

How can I declare a two-dimensional array of pointers and initialize it by null pointers in c++ ?
I tried to do this
int *arr[20][30]= nullptr;
You can aggregate initialize the array with empty initializer list,
int *arr[20][30] {};
// or
int *arr[20][30] = {};
(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 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).
Then all the elements of arr (i.e. the sub-array int* [30]) would be aggregate-initialized with empty initializer list too, then all the elements of sub-array with type int* would be value-initialized,
otherwise, the object is zero-initialized.
At last elements with type int* (which is built-in type) are all zero-initialized to null pointers.
If T is a scalar type, the object's initial value is the integral constant zero explicitly converted to T.

C++11 class member initialization

Just switched to C++11 from C++03, and I was wondering, is the following defined to always zero initialize the array data for all elements?
template<size_t COUNT>
class Test {
public:
uint32 data[COUNT] = {};
};
Yes it's guaranteed; list initialization turns to aggregate initialization for array type:
Otherwise, if T is an aggregate type, aggregate initialization is performed.
then for aggregate initialization:
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are initialized 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).
So all the elements of data will be value initialized, for uint32 they'll be zero-initialized at last.
otherwise, the object is zero-initialized.

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.

WCHAR wszFoo[CONSTANT_BAR] = {0}; <-- What does {0} mean?

WCHAR wszFoo[CONSTANT_BAR] = {0};
I've never seen something like {0} used in C++ as part of the language. And I have no idea how to search for a question like this online. What is it?
See array initialization.
Missing initialization values use zero
If an explicit array size is
specified, but an shorter
initiliazation list is specified, the
unspecified elements are set to zero.
float pressure[10] = {2.101, 2.32,
1.44};
This not only initializes the first
three values, but all remaining
elements are set to 0.0. To initialize
an array to all zeros, initialize only
the first value.
$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)."
All this means, is that there is an explict request to initialize first element to 0. Since initializers are not specified for the remaining elements, they are value-initialized. This in case of WCHARs means are initialized to 0.
What does value initialized means? Here is what the Standard says in $8.5 (italics are mine)
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 <------
WCHAR will fit here
To zero-initialize an object of type T
means:
— if T is a scalar type (3.9),
the object is set to the value of 0
(zero) converted to T; <------ WCHAR
will fit here
— if T is a non-union
class type, each nonstatic data member
and each base-class subobject is
zeroinitialized;
— if T is a union
type, the object’s first named data
member89) is zero-initialized;
— if T
is an array type, each element is
zero-initialized;
— if T is a
reference type, no initialization is
performed.
It's initializing an array.
float p1[1000]; // No intitialization.
float p2[1000] = {0.0}; // All 1000 values initialized to zero.
More here: C++ Notes: Array Initialization
It means initialize all elements of wszFoo to zero.