"struct a a1 = {0};" different from "struct a a2 = {5};" why? - c

If struct a a1 = {0}; initializes all the elements (of different types) of a structure to zero, then struct a a2 = {5}; should initialize it to 5.. no?
#include <stdio.h>
typedef struct _a {
int i;
int j;
int k;
}a;
int main(void)
{
a a0;
a a1 = {0};
a a2 = {5};
printf("a0.i = %d \n", a0.i);
printf("a0.j = %d \n", a0.j);
printf("a0.k = %d \n", a0.k);
printf("a1.i = %d \n", a1.i);
printf("a1.j = %d \n", a1.j);
printf("a1.k = %d \n", a1.k);
printf("a2.i = %d \n", a2.i);
printf("a2.j = %d \n", a2.j);
printf("a2.k = %d \n", a2.k);
return 0;
}
The uninitialized struct contains garbage values
a0.i = 134513937
a0.j = 134513456
a0.k = 0
The initialized to 0 struct contains all elements initialized to 0
a1.i = 0
a1.j = 0
a1.k = 0
The initialized to 5 struct contains only the first element initialized to 5 and the rest of the elements initialized to 0.
a2.i = 5
a2.j = 0
a2.k = 0
Would a2.j and a2.k always guaranteed to initialize to 0 during a a2 = {5}; (or) is it an undefined behavior
OTOH, why am I not seeing all the elements of s2 initialized to 5. How is the struct initialization is done during {0} and how is it different when {5} is used?

Reference:
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.
[EDIT]
Static objects and implicit initialization:
The storage duration of an object determines the lifetime of an object.
There are 3 storage durations:
static, automatic, and allocated
variables declared outside of all blocks and those explicitly declared with the static storage class specifier have static storage duration. Static variables are initialized to zero by default by the compiler.
Consider the following program:
#include<stdio.h>
int main()
{
int i;
static int j;
printf("i = [%d]",i);
printf("j = [%d]",j);
return 0;
}
In the above program, i has automatic storage and since it is not explicitly initialized its value is Undefined.
While j has static storage duration and it is guaranteed to be initialized to 0 by the compiler.

The omitted values will be always initialized to zero, because the standard says so. So you have essentially
struct a a1 = { 0, 0, 0 };
and
struct a a2 = { 5, 0, 0 };
which is of course different.

No. In C, if your initializer list is incomplete, all missing indices will be filled with 0. So this:
int a[3] = {0};
int b[3] = {5};
effectively becomes:
int a[3] = {0, 0, 0};
int b[3] = {5, 0, 0};
This is why it seemingly works with {0} but fails with {5}.

It doesn't work for
struct x {
int *y;
/* ... */
};
struct x xobj = {5};

Take a look at Designated Initializers in GCC documentation.

The behavior is exactly the same in both cases. If there are fewer initializers than there are elements in the aggregate, then the remaining elements are initialized as though they were declared static, meaning they'll be initialized to 0 or NULL.
It's just that in the first case, the explicit initializer has the same value as the implicit initializer.
If you want to initialize all the elements of your aggregate to something other than 0, then you will have to provide an explicit initializer for each of them, i.e.:
a a2 = {5, 5, 5};

Related

why is this printing 4 5 6 0 0 instead of 4 5 6 junk_value junk_value [duplicate]

This question already has answers here:
how does array[100] = {0} set the entire array to 0?
(4 answers)
Closed 3 years ago.
#include<stdio.h>
void m(int *p){
int i=0;
for(int i=0;i<5;i++)
printf("%d",p[i]);
}
int main(){
int a[5]={4,5,6};
m(a);
}
I expect the output will be 4 5 6 junkValue junkValue ,but the actual output is 4 5 6 0 0
In section "6.7.9 Initialization" of the standard it says:
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
As int is zero initialized when used as static objects, the code:
int a[5]={4,5,6};
is really the same as
int a[5]={4,5,6,0,0};
So there will be no "junk values" printed. It will (and must) print the two zeros.
In C there is no partial initialization.
An object either is not initialized or is fully 100% initialized (to 0 of the right kind in the absence of any other initializer)
int a[5] = {4, 5, 6}; // a[0] = 4, ..., a[3] = a[4] = 0;
int b[5]; // uninitialized
b[0] = 4;
b[1] = 5;
b[2] = 6;
m(b); // b[3] and b[4] have not been initialized/assigned
// accessing them is UB
int a[5]={4,5,6}; is a partially initialized array. Uninitialized array elements a[3], a[4] are initialized to zero. So this is expected behavior.

The behaviour of unions in C

I am really dumb. Please help me out by explaining the output:
#include <stdio.h>
union x
{
int a;
char b;
double c;
};
int main()
{
union x x[3] = {{1}, {'a'}, {1.2}};
int i;
for(i = 0; i < 3; i++)
printf("%d , %d , %lf\n", x[i].a, x[i].b, x[i].c);
return 0;
}
Output:
When you provide an initial value for a union, the compiler assigns it to the first member of the union. So, given:
union x
{
int a;
char b;
double c;
};
and:
union x x[3] = {{1}, {'a'}, {1.2}};
the compiler initializes x[0].a to 1, x[1].a to a, and x[2].a to 1.2. The compiler does not use the types of the initial values to match them to union elements. It merely initializes the first member with the value you give it. If there is a difference in types, the compiler converts the value to the type of the first member. (If that is a legal conversion. Otherwise, the compiler should provide a warning or error message.)
To initialize specific members of the union, you can use designated initializers, in which you explicitly name the member of the union you want to initialize:
union x x[3] = { { .a = 1 }, { .b = 'a' }, { .c = 1.2 } };
think of a union as an allocated space in the memory (size of which is the largest element in the union) each union defined can be interpeted as either element of the union so you can look at that allocated memory as a different type
https://www.tutorialspoint.com/cprogramming/c_unions.htm
taken from the link:
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main( ) {
union Data data;
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
return 0;
}
as you can see it has defined one union but it used three different times as a different type
EDIT:
by C99 when initalizing a union the first element is the one initialized hence the value 1.2 is casted to 1 where in the case of the char the casting works as expected
if you reorder the elements in your union you will get:
0 , 0 , 1.000000
0 , 0 , 97.000000
858993459 , 51 , 1.200000
for further explanation:
http://en.cppreference.com/w/c/language/struct_initialization
When initializing a struct, the first initializer in the list
initializes the first declared member (unless a designator is
specified) (since C99), and all subsequent initializers without
designators (since C99)initialize the struct members declared after
the one initialized by the previous expression.
as mentioned in other comments there is a lot of information on the issue and you should research it further, but i hope this gives you a starting point
As per C99 standard, you can still initialize your union with one-liner using designated initializers without losing your data:
union x x[3] = {{.a = 1}, {.b = 'a'}, {.c = 1.2}};
This will force compiler to use particular union's member, rather than type of first declared one (which is int in your case).
Output:
1, 1, 0.000000
97, 97, 0.000000
858993459, 51, 1.200000
Proof.

What are elements of an array in C initialized to after making the array?

So when I create an array in the programming language c, what are all of the elements initially initialized to? For instance,
char array[5];
Creates an array with 5 elements. What are the elements initially? I printed the elements out, but it seemed to be random, so are they just created randomly, or is there a method to how they are made?
"What are the elements initially" will depend on where and how your array is defined.
A automatic array defined in block scope will contain garbage. Meanwhile, a static array will be initialized with zeros.
char a[5]; /* zeros */
int main()
{
static char b[5]; /* zeros */
char c[5]; /* garbage */
}
If the array is declared as a struct member, then the above rules apply to the definition of the containing struct object.
It depends where you initialize them.
Global : All the values in the array will be 0
Local : The values will be some garbage value.Its random.
The contents of an uninitialized array (or any uninitialized object) are undetermined. Accessing them invokes Undefined Behaviour.
char a[5], b[5] = {1, 2, 3, 4, 5}, c[5] = {42};
printf("%d\n", a[1]); // UB
printf("%d\n", b[1]); // 2
printf("%d\n", c[1]); // 0
Note that static objects or global scope objects have a default zero initialization.

Array initialization C

What is the meaning of this initialization:
char arr[10] = { 0, };
I'm familiar with char arr[10] = {0}; which sets all the elements to zero, and with char arr[10] = {1,2}; which sets the first two elements to 1 and 2 (ascii) and the rest to 0.
I'm not familiar with the format above.
A quick test showed that it's probably just like char arr[10] = {0};, but is there other meaning I'm not aware of?
From How to initialize all members of an array to the same value?:
Initialize all members to the same value:
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
Elements with missing values will be initialized to 0:
int myArray[10] = { 1, 2 }; //initialize to 1,2,0,0,0...
So this will initialize all elements to 0:
int myArray[10] = { 0 }; //all elements 0
In C++, an empty initialization list will also initialize every element to 0:
int myArray[10] = {}; //all elements 0 in C++
Objects with static storage duration will initialize to 0 if no initializer is specified:
static int myArray[10]; //all elements 0
If your compiler is GCC you can use following syntax:
int array[1024] = {[0 ... 1023] = 5};
int A[10] = {[0 ... 4] = 5, [5 ... 9] = 3};
Yes, it's equivalent with the version without the trailing comma.
See this question for more discussion about trailing commas.
As standard
A trailing comma may appear after the last expression in an array initializer and is ignored
char arr[10] = { 0, }; and char arr[10] = {0} is same in this case.
But char arr[10] = {5, } is different. 5 will be stored in a[0] and remaining will be filled with zero.
I suggest not to use this for global variables, because it will increase the data section size.
There is no difference between int arr[3] ={0,}; and int arr[3] ={0};.
Ref: C11 6.7.9:
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
Both forms of initializer lists are considered initializers. The form with the comma at the end is preferred by many because it makes it easier to rearrange or add elements to the list during code maintenance.
int arr[3] ={0,};
declares an array of three elements and initializes the first element to 0. When you do a partial initialization, the rest of the array is automatically initialized with zeros.
Ref. C11 6.7.9:
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 wrote this answer for another question, but it got dup closed. I liked the answer though, so I'm reposting on the original question.]

unspecified dimension of array initialisation with {}

I am wondering if:
int a[] = {1, 2};
allocates sizeof(int) * number of constants inside brackets
int a[5] = {1, 2};
assigns constants to array fields from 0 to 1 and then fills with 0
int a[5] = {};
fills with 0
What happens when I do:
int a[] = {};
Thanks.
int a[5] = {};
and
int a[] = {};
are not valid C definitions.
In GNU C (C with gcc extensions), you can use empty {} and it is considered the same as {0}.
Note that int [] is a incomplete type. When initializing an array of an incomplete type with explicit initializers, the type is completed and the number of elements of the array is then the number of elements in the brace enclosed initializer list.
So int a[] = {0}; defines an array of 1 element in C and in GNU C int a[] = {}; does the same.

Resources