all:
In C language:
struct A
{
int a;
int b;
};
A aa = {0};
This statement initialize aa.a only or initialize the whole struture? Or the behavior depends on Compiler?
Thanks in advance!
One more ex:
struct A
{
int a;
int b;
};
struct A aa = {5};
This will initialize the whole structure but aa.b will be initialized to 0.
If you initialize only few members of a structure then all other members of that will be automatically initialized to 0.
From the standard (N1570)
6.7.9 Initialization
...
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 in your example aa.a would be explicitly initialized to 0 due to the initializer, while aa.b would be implicitly initialized to 0 because of the clauses above.
According to the C99 standard, section 6.7.8.17, only the first member (in declaration order, i.e. the a field) is initialized explicitly in your example:
Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first named member of a union.
By "designation" the standard means
A aa = {.b = 0};
This is a more precise way of letting programmers decide what fields get initialized.
This statement initialize aa.a only or initialize the whole struture?
Have a look at the example below , initializing the structure with {3} , is similar to initializing with {3,0}.
Hence in your program when you initialize with {0} , you are actually initializing both a and b (the whole structure) , with {0,0}
#include<stdio.h>
typedef struct A
{
int a;
int b;
}a;
int main()
{
a aa = {3};
printf("\na1 = %d",aa.a);
printf("\nb1 = %d",aa.b);
a bb = {3,0};
printf("\na2 = %d",bb.a);
printf("\nb2 = %d",bb.b);
}
Related
Say I have a struct typedef that is:
typedef struct {
int32_t memberOne;
int32_t memberTwo;
} myStruct_t;
I instantiate a const of that type as follows:
const myStruct_t myConst = {.memberTwo = 32};
What does C say the compiler should set memberOne to be? I've tried it, of course, and I happen to get 0 on the compilers I've tried, what I'm after here is does the C standard require uninitialised members of a const struct to be initialised to something or other by the compiler, i.e. would the code above be considered portable? Clause 6.7.9 of C99 says:
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;
...but what about consts? Are they considered to be of static storage type, just without the static keyword?
does the C standard require uninitialised members of a const struct to be initialised to something
Yes, they are guaranteed to be set to zero/null pointers as long as you initialize at least one member explicitly. const plays no part in it.
You've already found the relevant part about how objects with static storage duration are initialized. Just keep reading the same chapter:
C17 6.7.9 §19
The initialization shall occur in initializer list order, each initializer provided for a
particular subobject overriding any previously listed initializer for the same subobject;
all subobjects that are not initialized explicitly shall be initialized implicitly the same as
objects that have static storage duration.
C17 6.7.9 §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.
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.
A work colleague recommended to initialize a struct with {'\0'} instead of {0} because he explained that0 is considered to be an int thus at least 4 bytes. Therefore if a struct is not a multiple of 4 initializing the struct to 0 may leave some bytes not initialized to 0 while because \0 is an ASCII char of size 1 byte it will initialize a struct to zero regardless of its size.
That being said I almost never saw initialization using {'\0'} while I did see lots of initializations using {0}.
My question is whether initializing a struct with {0} is enough? Is it enough because most compilers will automatically pad the bytes which are not multiple of 4 with zeroes or is it because C does it?
No, there is no difference.
For one, '\0' is not "one byte"; in C, character constants have type int, so '\0' and 0 are 100% equivalent in every context. (You can check this with sizeof: Both sizeof 0 and sizeof '\0' will yield the same value, typically 4 or 8.)
The other reason is explained in the initialization rules of C (in C99 that's 6.7.8 Initialization):
[...]
Otherwise, the initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members.
Each brace-enclosed initializer list has an associated current object. When no
designations are present, subobjects of the current object are initialized in order according
to the type of the current object: array elements in increasing subscript order, structure
members in declaration order, and the first named member of a union. [...]
This says the members of the initialization list are used to initialize the fields of a struct or array in order; it doesn't matter how many bytes they have.
If you write
struct foo { double x; };
struct foo var = { 0 };
then 0 (the first initializer value, type int) is used to initialize the first struct field (x, type double). It's as if you had written double x = 0. The effect is that the value of 0 is implicitly converted from int to double and stored in the variable.
Furthermore, if there are fewer initializers than struct or array elements, this rule kicks in:
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 how does implicit initialization work with static objects?
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.
This means all not-explicitly-initialized members of an array or struct are implicitly set to 0.
Yes, initializing a struct with {0} is enough. Understand the compiler doesn't assign the memory to struct based on the initialization. A struct independent of whether it's filled with some value or not will always require the same memory.
e.g.
#include <stdio.h>
struct A {
char a;
};
struct B {
int b;
};
int main(void) {
struct A b = {'\0'};
struct A c = {0};
printf("%zu %zu\n",sizeof(b),sizeof(c));
struct B ab = {'\0'};
struct B ac = {0};
printf("%zu %zu\n",sizeof(ab),sizeof(ac));
return 0;
}
The answers will always be the same independent of how you assign it.
This question already has answers here:
What happens to fields not named by a designated initializer?
(1 answer)
Why is this array having all remaining values initialized to zero?
(4 answers)
Closed 5 years ago.
I have a struct array. Only a few index locations need to be initialized. Is there a compiler attribute that ensures that the uninitialized combinations are init'd to 0 ?
For example:
If I have a statically init'd struct array as below, how can I ensure that the remaining 3 elements in that array (which are not explicitly pre-init'd) are zero'd out ?
typedef struct foo_s {
int a;
int b;
} foo_t;
foo_t foo_array[4] = {
{ .a = 1, .b = 2 },
};
Thanks,
The behavior you want is already part of standard C. There are no "half-initialized" variables; if you only initialize part of something, then all remaining elements will be zero-initialized.
Besides, you say (in your title) that this array is global. That means it has static storage duration, so it will be zero-initialized even if you don't provide any initializer at all.
Quoting C99 on aggregate initializers:
6.7.8/19:
[...] all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
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.
6.7.8/10:
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.
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.