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
Related
The following example is from Stroustrup C++ 4th Ed. Page 519. It was my understanding from K&R C and earlier in the Stroustrup book that local automatic variables of primitive types are undefined or not known to be initialized. Static variables of primitive types or automatic variables of a class with a default constructor are initialized.
That would mean int b should be undefined and not known to be initialized. Yet, Stroustrup adds the following code comment saying b = 0. Is this Errata? Or perhaps some behavior of calling with the default constructor?
Thank you
struct S {
string a;
int b;
};
void f(void) {
S s0 {}; // default construction: {"",0}
// ...
}
It's easy. You can leave the built-in type variables uninitialized or you can ask the compiler to zero-initialize them.
S s1; // string is default initialized, int is left uninitialized
S s2{}; // All fields are initialized.
Notice the {}. That (in this case) asks the compiler to initialize all fields.
In this line:
S s0 {};
the syntax that is used is value-initialization, in particular
when a named variable (automatic, static, or thread-local) is declared with the initializer consisting of a pair of braces.
In this case, the effect of value-initialization is that the object s0 is zero-initialized.
In this particular case, the effect is:
If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
which implies that the int member b is zero-initialized to the value 0.
Are local automatic variables initialized or not?
It depends on the initialisation syntax that is used, the type of the variable, as well as the storage class.
That would mean int b should be undefined
No, because the example uses value initialisation, and the class in question is an aggregate.
I came upon this interesting answer when our team was dealing with a valgrind warning about unitialized members of a POD in our C++ code:
https://stackoverflow.com/a/5914697/629530
Restating the salient points, consider the following POD structure in C++:
struct C
{
int x;
int y;
};
The following invocations of constructing an object of type C invokes the default constructor and the members are initialized with that default constructor (again, copying the code and comments from Martin York's answer):
C c = C(); // Zero initialize using default constructor
C c{}; // Latest versions accept this syntax.
C* c = new C(); // Zero initialize a dynamically allocated object.
Makes sense. Martin York goes on to point out that the with the following declarations, however, the members of c are not initialized via a constructor and therefore contain undefined data:
C c; // members are random
C* c = new C; // members are random (more officially undefined).
That's interesting. I had used braced-init-list initialization of POD types before, but I didn't realize that C c; would not call the default constructor for a POD type. His answer satisfies the question, but I'd like to know specifically what is instantiated when the latter, non-default constructed c objects are declared. Specifically, the following would be helpful to me:
What is the official name for this non-default initialization of POD types? I'm having trouble googling for this mechanism because I don't know its name.
If the POD type has something less trivial than an int-type, such as a std::string, is the memory for that member also initialized with undefined values? Or is the default constructor for a std::string called for that member?
Update.
Thanks for the input. This has been duplicated to a question with this single answer:
https://stackoverflow.com/a/8860787/629530
According to that answer (and the answers to the question it is duplicated to), a declaration of the form without a parentheses is called "default initialized":
Info *p = new Info; <------- Default Initialization
For default initialization, these points about initialization are made:
To default-initialize an object of type T means:
if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is an array type, each element is default-initialized;
otherwise, the object is zero-initialized.
I might be misunderstanding something, but the struct named C proposed above is a POD type that is not an array. Thus it should be zero initialized? The members are not, however, zero initialized but contain undefined values. How do I reconcile this?
default-initialize an object of type T means:
... otherwise, the object is zero-initialized.
No.
Your first linked answer is correct about C++11 onwards, and this is called default-initialization. It's different to default-construction or value initialization.
The second linked answer was probably correct for C++03, but is wrong for C++11 onwards (even though it was written in 2012). I don't have a copy of the '03 standard to verify, and it was a long time ago.
The effects of default initialization are:
if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
if T is an array type, every element of the array is default-initialized;
otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
Local copy of N4659 agrees with the summary above:
11.6 Initializers [dcl.init]
...
(7.3) Otherwise, no initialization is performed
The section on new-expressions even refers to 11.6 and then says
Note: If no initialization is performed, the object has an indeterminate value.— end note
Current draft has
9.3 Initializers [dcl.init]
...
(7.3) Otherwise, no initialization is performed.
Note: We are speaking about (supposedly) C++98 compliant compilers, here. This is not a C++11 question.
We have a strange behavior in one of our compilers and we're not sure if this is Ok or if this is a compiler bug:
// This struct has a default constructor
struct AAA
{
AAA() : value(0) {}
int value ;
} ;
// This struct has a member of type AAA and an array of int, both surrounded
// by ints
struct BBB
{
int m_a ;
AAA m_b ;
int m_c ;
int m_d[42] ;
} ;
When BBB is initialized as such:
BBB bbb = {0} ;
We expected all the POD members of BBB (including m_d, the array of ints) to be zero-initialized, and all the non-POD members of BBB to be constructed.
This worked on the native compiler of AIX, on Linux/GCC-3.4, on Windows/VisualC++... But not on Solaris/SunStudio, where only the non-arrays members are zero-initialized.
We did a little research, in the C++98 standard (a draft document), where we found the following:
[12.6.1 - 2]
When an aggregate (whether class or array) contains members of class type and is initialized by a brace-enclosed initializer-list (8.5.1), each such member is copy-initialized (see 8.5) by the corresponding assignment-expression. If there are fewer initializers in the initializer-list than members of the aggregate, each member not explicitly initialized shall be default-initialized (8.5).
Then:
[8.5 - 5]
To zero-initialize storage for an object of type T means:
— if T is a scalar type (3.9), the storage is set to the value of 0 (zero) converted to T ;
— if T is a non-union class type, the storage for each nonstatic data member and each base-class subobject is zero-initialized;
— if T is a union type, the storage for its first data member 89) is zero-initialized;
— if T is an array type, the storage for each element is zero-initialized;
— if T is a reference type, no initialization is performed.
And then:
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, the storage for the object is zero-initialized.
The way I read it: SunStudio should zero-initialize the array of ints (BBB::m_d)
Strange thing: if we remove the default constructor from AAA, then everything in BBB is zero-initialized.
QUESTION: Is SunStudio behavior standard when it fails to zero-initialize an array of ints of a struct containing a non-POD? Or is this a compiler bug?
It is indeed a bug with Sun/Solaris.
What you've written is indeed what is supposed to happen and you are correct with everything you write.
This is clearly an error in Sun CC. The standard is clear, and your understanding of it is correct.
It seems to be a bug - I have no experience with Solaris compilers, but all other compilers I've worked with will allow this sort of initialization.
I would suggest that work around the problem by being more explicit:
BBB bbb = {0, 0, 0, {0} };
class Foo {};
int main()
{
Foo *foo[500] = { NULL};
}
Regardless of O.S/compiler is it standard that the whole array will be set to NULL?
Yes it is valid and guaranteed by the C++ Standard.
Reference:
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. ]
Value Initialization is defined under:
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
If you mean the construct with a single {NULL} where you would have expected to see 500 NULLs, yes, that is valid.
(Personally I make it a habit to end such lists with a comma {NULL,} to make it obvious that there are more implicit values, but that's just a matter of style.)
It is not necessary , that you set it to NULL
If you wont the array will be having garbage values
"Plain old C" structures and aggregates which are initialized are fully initialized. That comes from C. The members which do not have an initializer are initialized to zero. (Whatever zero means for their type: null pointer, or 0.0 floating-point value).
In C++, the members can be of class type with constructors. Such members which have no initializer are initialized by their default constructors.
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.