I have an array of 3 elements. But I only want to initialize 2 of them.
I let the third element blank.
unsigned char array[3] = {1,2,};
int main(){
printf("%d",array[2]);
return 0;
}
The print result is 0. I tested it on IAR, and some online compiler.
Is there any C rule for the value of third element?
Is there any compiler filling the third element by 0xFF ? (Especially cross compiler)
Yes, the C standard does define what happens in this case. So no, there should be no C standard compliant compiler that intialises with 0xFF in this case.
Section 6.7.9 of the standard says:
Initialisation
...
10 ...If an object that has static or thread storage duration is not
initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is
initialized to (positive or unsigned) zero;
if it is an aggregate,
every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized to zero bits;
...
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.
From this post, it appears that that syntax will initialize all elements after the comma to zero. Moreover; all uninitialized data in the data segment of the program (in other words all uninitialized global variables) are automatically set to zero, so if you are looking for undefined behavior in this program, there isn't any; it will always be 0.
This can be achieved with gcc extension as below
unsigned char array[10] = {1,2,[2 ... 9] = 0xFF};
Related
While revising my C knowledge, I stumbled into the following example:
#include <stdio.h>
/* Just a simple structure */
typedef struct lab {
int num;
char *str;
} bal;
int main (void) {
/* Declare and _partially_ initialize an array of the structure above... */
bal struct_array[10] = { {0, NULL} };
/* Question: what does _exacly_ happen to the other 9 members of the array? */
return 0;
};
The comment in the code should be enough to provide my question. In other words, what does it happen if we partially initialize an array of structs? Sure, I know that (at least) for C++11 there is the default initialization. But does it hold for pure C, too? If yes, is it true for all the standards (from C89 on), or just for some in particular? Thank you.
If an array or struct is only partially initialized, any containing objects without an explicit initializer are set to 0 or NULL.
Partial initialization is covered in section 6.7.9p21 of the C11 standard:
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.
And initialization of objects with static storage duration are covered in section 6.7.9p10:
If an object that has automatic storage duration is not
initialized explicitly, its value is indeterminate. If an
object that has static or thread storage duration is not
initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or unsigned) zero;
if it is an aggregate, every member is initialized (recursively) according to these rules,and any padding is initialized to zero bits;
if it is a union, the first named member is initialized (recursively) according to these rules, and any padding is initialized
to zero bits
So in your particular case, all array elements will have the num member set to 0 and the str member set to NULL.
This question already has answers here:
what is the difference between struct {0} and memset 0 [duplicate]
(2 answers)
memset() or value initialization to zero out a struct?
(8 answers)
Closed 4 years ago.
I have following structure and i want to initialize it to zero.
struct example {
int a;
int b;
char c;
};
struct example mystruct;
I can memset mystruct to zero in following ways:
memset(&mystruct, 0, sizeof(mystruct));
or
mystruct = (struct example) {0};
Is the second way is equal to the first one?
Note that i want to initialize mystruct variable to zero not only at variable definition, maybe for reusing it.
Well, in your case, they will be equivalent (disregarding the padding bytes).
Quoting C11, chapter §6.7.9/ P21, (emphasis mine)
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.
and, regarding the initialization of static storage duration objects, P10 (again emphasis mine)
[...] If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
For sake of completeness, as mentioned in the below comment by Serge Ballesta:
all remaining members will be initialized implicitly the same as objects that have static storage duration. And the standard does not mandate anything for the padding bits of the top level object
which indicates, the assignment will differ from the memset() call in case of the first object / member, for the padding values.
No, they are not equal.
The first is more low-level, it will set all bits of the value to 0, including those that are not part of any member (padding).
The latter is only guaranteed to set the actual members to zero, so it might be faster since it has the opportunity to touch less memory.
This question already has answers here:
Why is this array having all remaining values initialized to zero?
(4 answers)
Does a string literal count as a partial initializer and zero-initialize?
(3 answers)
Closed 4 years ago.
//Language C
int main()
{
int a[5]={0};
for(int i=0 ; i < 4 ; i++ )
printf("%d",a[i]);
}
}
The output of the following was 1000 in gcc. But I thought it should print 1 and rest garbage values as I have not assigned values to other array locations.
If compiler version is not taken in account, is my thinking right? Or I am missing something.
The C standard (citing the latest C11 draft N1570 here) explains this quite well.
§6.7.9 Initialization, p21:
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.
(emphasis mine)
so, every element except a[0] in your code is initialized implicitly. Now let's look what that means:
§6.7.9 Initialization, p10:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
(again, emphasis mine)
so, a[1] to a[4] are initialized to 0 -- type int is an arithmetic type.
By default, the local arrays are stored in stack. Uninitialised local arrays would be allocated garbage values.
But why does this syntax int array[10] = {0}; initialises all array elements to zero by default? Even if I give int array[10] = {10, 20}; //It initialises all rest of the elements to zero.
Isn't it being stored on stack in this case? How does it initialise them all to zero?
Whether or not a local array is initialized has no bearing on whether or not it is stored on stack.
If the implementation uses a stack, then the array will be on the stack, initialized or not.
From section 6.7.9 of the C standard:
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an
object that has static or thread storage duration is not
initialized explicitly, then:
— if it has pointer type, it is
initialized to a null pointer;
— if it has arithmetic type, it is
initialized to (positive or unsigned) zero;
— if it is an aggregate,
every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
— if it is a union, the
first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
...
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.
So if an initializer list has fewer elements than the array, the remaining elements are initialized the same as non local variables, i.e. set to 0.
Suppose the following initialization:
char mystr[4] = "";
Does the C99 standard guarantee that a character array initialized to an empty string will initialize all elements in the character array to null bytes? For example, does the standard guarantee that mystr[2] == '\0'?
How about these initializations:
char myfoo[4] = { '\0' };
char mybar[4] = { 0 };
While I'm pretty certain that explicitly setting the first element of a character array will guarantee the implicit initialization of the rest of the elements to 0, I suspect a string literal initialization results in a copy to the array -- thus meaning a single \0 is copied to the array while the remaining elements are left uninitialized.
Section 6.7.8, paragraph 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.
And how are objects with static storage duration initialized?
Section 6.7.8, paragraph 10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or unsigned) zero;
if it is an aggregate, every member is initialized (recursively) according to these rules;
if it is a union, the first named member is initialized (recursively) according to these
rules.
char is an arithmetic type, so it's initialized to 0. Huzzah, you can rest easy.
C language follows "all or nothing" approach to all aggregate initializations. It means that any attempt to supply an explicit initializer for any part of the aggregate (regardless of how small that part is) immediately guarantees that the entire aggregate will be initialized. The parts without an explicit initializer will be zero-initialized.
In your example the entire array is guaranteed to be initialized with zeros. In case of struct initialization, all fields that are not initialized explicitly get zero values.
One consequence of that principle is that in C language the = { 0 } initializer serves as an idiomatic universal zero initializer. Since the language allows = { value } syntax in scalar object initializers as well, one can use = { 0 } to initialize any object to all-zero state
#define UNIVERSAL_ZERO { 0 }
double d = UNIVERSAL_ZERO;
char s[100] = UNIVERSAL_ZERO;
struct { int x, y, z; } xyz = UNIVERSAL_ZERO;
int *p = UNIVERSAL_ZERO;
Yes, excess elements of an array are always zero-initialized, and arrays of char initialized using a string literal are no exception either.
From the C99 Standard, section 6.7.8.21 (page 139 of this document):
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.