Array initialization C - 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.]

Related

Initialize an array using the pointer to an existing array

I have already understood that one can't assign arrays to arrays in c. A statement like:
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int array2[10];
int * array3 = array;
Is valid, but a consecutive statement:
array2 = array1;
Is not, because arrays do decay to pointers. I find this not satisfying, since in case I have a function that creates an array:
int * arrcreate() {
static int funcarray[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
return funcarray
}
And I call it in my main routine, I'd like to handle an array, not a pointer.
Of course I could in my main program create an array and fill it by hand:
int main() {
int array[10];
int i;
int * p = arrcreate();
for(i = 0; i<10, i++) {
array[i] = p[i];
}
}
But since I KNOW that when initializing an array it is possible to do kind of an assignment:
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
I wanted to ask if it is possible to assign an array with the pointer to an array as well.
An equivalent question would be: Given a pointer to an array, and knowing the size of the array the pointer is pointing to, is it possible to create and initialize on the fly a new array, which is in every matter a copy of the old one?
As Bathsheba said, an array cannot be on the left hand side of an assignment like the one you put in your question. But if you will always know both the pointer to the array you would like to copy, as well as the array size, you could write a function along the lines of:
void copy_array(const int *a, const int arraySize, int **b) {
*b = malloc(arraySize * sizeof(*a));
for (int indx = 0; indx < arraySize; indx++) {
(*b)[indx] = a[indx];
}
}
int main() {
int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *array2;
copy_array(array1, &array2);
// do stuff
free(array2);
}
Is that an option?
Unfortunately the answer is not. The draft n1570 for C11 says in 6.7.9 Initialization:
...16 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.
(the previous items concern struct, union or character type array)
That means that an int array can only be initialized with a brace enclosed list of integer values. And a pointer to an array does not follow that definition.
Informally speaking, an array cannot be an lvalue. This means that an array cannot be on the left hand side of an assignment.
Note secondly that int array1[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; is not an assignment but is array initialisation.
If you're careless regarding terminology, the two sentences appear to be in contradiction. But they are not; furthermore you can see that it is not possible to initialise an array using the values pointed at by a particular pointer. You need to use something on the lines of memcpy.

Initialize an array in C error "expected expression before ‘]’ token"

When I declare an array like this.
int array[4] = {1, 2, 3, 4};
// do some calculation here with array.
.................
// After that, I set the elements of array as '0' here.
memset(array, 0, sizeof array);
// Right now the elements in array are all '0'.
// I want to initialize the array with different elements.
array[] = {1, 2, 3, 4}; // I got error here:
// error: expected expression before ‘{’ token
// Even I change to array[] = {1, 2, 3, 4}, it still give me same.
Could everyone tell me why I cannot use the same array to re-initialize it like Java. I already clear the array elements as '0' here.
Do I have to name a different array from fresh and initialize it?
I cannot use the previous defined array later?
Thank you
You can only "initialize" once. That's why it's called "initialization".
What you are attempting to do here is assignment, and you have two main problems:
The array is called array, not array[];
Arrays cannot be assigned to.
You will have to assign the elements one by one, or re-fill the array in batch.
And Java is entirely irrelevant, as are sunglasses and llamas.
Arrays do not have the copy assignment operator and may not use a braced-init list for assigning.
So you have to assign each element of an array individually.
Another approach is to use a structure as a wrapper around an array. In this case you may use the copy assignment operator by means of compound literals.
Here is a demonstrative program
#include <stdio.h>
int main( void )
{
struct array
{
int a[4];
} myArray = { { 1, 2, 3, 4 } };
for ( size_t i = 0; i < 4; i++ ) printf( "%d ", myArray.a[i] );
printf( "\n" );
myArray = ( struct array ) { { 5, 6, 7, 9 } };
for ( size_t i = 0; i < 4; i++ ) printf( "%d ", myArray.a[i] );
printf( "\n" );
}
Its output is
1 2 3 4
5 6 7 9
Another advantage of this approach is that you may use such a structure as a return type of functions allowing to return in fact arrays.
int array[4] = {1,2,3,4};
//do some calculation with array
// After that, I set the elements of array as '0' here.
memset(array,0,sizeof(array));
// Right now the elements in array are all '0'.
// I want to initialize the array with different elements.
int array2[4] = {1, 2, 3, 4};
memcpy(array, array2, sizeof(array2));

How to set all elements of an array to zero or any same value? [duplicate]

This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
Closed 8 years ago.
I'm beginner in C and I really need an efficient method to set all elements of an array equal zero or any same value. My array is too long, so I don't want to do it with for loop.
If your array has static storage allocation, it is default initialized to zero. However, if the array has automatic storage allocation, then you can simply initialize all its elements to zero using an array initializer list which contains a zero.
// function scope
// this initializes all elements to 0
int arr[4] = {0};
// equivalent to
int arr[4] = {0, 0, 0, 0};
// file scope
int arr[4];
// equivalent to
int arr[4] = {0};
Please note that there is no standard way to initialize the elements of an array to a value other than zero using an initializer list which contains a single element (the value). You must explicitly initialize all elements of the array using the initializer list.
// initialize all elements to 4
int arr[4] = {4, 4, 4, 4};
// equivalent to
int arr[] = {4, 4, 4, 4};
You could use memset, if you sure about the length.
memset(ptr, 0x00, length)
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; // All elements of myArray are 5
int myArray[10] = { 0 }; // Will initialize all elements to 0
int myArray[10] = { 5 }; // Will initialize myArray[0] to 5 and other elements to 0
static int myArray[10]; // Will initialize all elements to 0
/************************************************************************************/
int myArray[10];// This will declare and define (allocate memory) but won’t initialize
int i; // Loop variable
for (i = 0; i < 10; ++i) // Using for loop we are initializing
{
myArray[i] = 5;
}
/************************************************************************************/
int myArray[10] = {[0 ... 9] = 5}; // This works only in GCC
If your array is static or global it's initialized to zero before main() starts. That would be the most efficient option.

Declaration of an array without highest dimension

what will be the dimension of integer array arr if declared like this :
int arr[][2]={1,2,3};
what is the use of not declaring the highest dimension ?
Somewhat to my surprise, your declaration:
int arr[][2]={1,2,3};
appears to be legal. You can legally omit inner braces in initializers. For example, if you wanted to define the bounds of arr explicitly and initialize all its elements, you could write either:
int arr[2][2] = { { 1, 2}, { 3, 4 } };
or, equivalently:
int arr[2][2] = { 1, 2, 3, 4 };
You can also omit trailing elements, and they'll be implicitly set to zero. For a one-dimensional array, this is straightforward; this:
int arr[4] = { 1, 2, 3 };
is equivalent to:
int arr[4] = { 1, 2, 3, 0 };
And if you omit a dimension, it can be inferred from the initializer:
int arr[] = { 1, 2, 3, 4 }; // 4 elements
Since you're defining arr as an array of 2-element arrays of int, this:
int arr[][2]={1,2,3};
is equivalent to this:
int arr[][2] = { { 1, 2 }, { 3 } };
You have two elements in the initializer (each of which initializes a 2-element array), so that's equivalent to:
int arr[2][2] = { { 1, 2 }, { 3 } };
Finally, you've omitted the last initializer sub-element, so it's implicitly zero:
int arr[2][2] = { { 1, 2 }, { 3, 0 } };
In general, omitting dimensions and trailing initializers is useful because it lets the compiler figure out certain things. If I write:
char message[] = "hello, world";
I don't have to count the characters in the string (and add 1 for the terminating '\0'). Computers are really good at counting things; making a human do that job would be silly.
Similarly, omitting some initializers lets you provide only the information you need. With C99's addition of designated initializers, you can even initialize a specified member of a structure and let the compiler take care of everything else:
struct foo obj = { .something = 42 };
As for flattening initializers by omitting inner curly braces, I personally don't see much use for that except for the special case of using a { 0 } initializer to initialize and entire array or structure to zero. In particular, for multidimensional arrays I find it much clearer to show the entire structure of the array.
Per the minimal bracketing rule (6.7.9p20 in C11),
enough initializers from the list are taken to account for the elements or members of the subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next element or member of the aggregate of which the current subaggregate or contained union is a part.
So the following declarations are equivalent:
int arr[][2]={1,2,3};
int arr[][2]={{1,2},{3}};
int arr[2][2]={{1,2},{3}};
As to why this is useful: when initializing a large multi-dimensional array, it may well be obvious to the reader how many items there are per subaggregate; in which case, there is no need to supply the brackets between subaggregates.

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