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

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));

Related

What is the difference between a regular array, and array of pointers

Can someone plz explain me what is the diffrence between those tow lines
and when we will want to use each one of then
int array[] = { 1, 2, 3 }; // init a regular array
int *numList = {1, 2, 3}; // init an array of pointers?
I am expecting that there are probably seenarios we will want to use the second over the first,
But when?
Thank You in Advance
You're conflating some concepts. As #ikegami noted, your second line:
int *numList = {1, 2, 3};
Gets treated as:
int *numList = 1;
Which not an array, nor a valid pointer.
If you want to create an array of pointers, you use the same syntax as normal arrays, with the type being a pointer:
int* numList[] = {
&array[0],
&array[1],
&array[2]
};
Will create an array of 3 int pointers, pointing to your original array's elements.

why I am not able to initialize array of pointers providing 2d array

int *p = ( int[] ){ 1, 2, 3, 4 };
Doing this I am able to initialize a anonymous array to a pointer p.
In a similar way I want to assign arrays of array (i.e. probably 2D array) in
array of pointers. And so I have tried the following code:
int *p[]= (int [][3]) { {1,2,3},{10,20,30} };
But it goes wrong, anyway if I assign it to a pointer to whole Array( as int (*p)[]= (int [][3]) { {1,2,3},{10,20,30} }; ) it works fine.
I am in confused that if a pointer can get assigned a anonymous array why the array of pointers could not get assigned to 2d array?
The compound literal
(int [][3]) { {1,2,3},{10,20,30} };
has the type
int [2][3]
i.e. array of 2 elements, each consisting of 3 int elements.
When used in the line
int *p[]= (int [][3]) { {1,2,3},{10,20,30} };
the array will decay to a pointer to the first element. This pointer will therefore have the type "pointer to array of 3 int elements`.
However, you cannot assign this data type to p, because the types are different. You declared p as an array of pointers. That is why your code is not working.
If you want p to be an array of pointers in which every pointer points to its array of int elements, then you will need to use several compound literals, one for each of these arrays:
int *p[] = {
( int[] ){ 1, 2, 3, 4 },
( int[] ){ 5, 6, 7, 8 },
( int[] ){ 9, 10, 11, 12 }
};
Here is a small test program:
#include <stdio.h>
int main( void )
{
int *p[] = {
( int[] ){ 1, 2, 3, 4 },
( int[] ){ 5, 6, 7, 8 },
( int[] ){ 9, 10, 11, 12 }
};
printf( "%d\n", p[1][2] );
}
This program has the output 7.
EDIT:
According to your remarks in the comments section of this answer, it seems that you have several 2D arrays and want to create an array of pointers to these arrays. In that case, you can do the following:
#include <stdio.h>
int main( void )
{
//define first 2D array
int arr1[][4] = {
{ 1, 2, 3, 4},
{ 5, 6, 7, 8},
{ 9, 10, 11, 12}
};
//define second 2D array
int arr2[][4] = {
{ 13, 14, 15, 16},
{ 17, 18, 19, 20},
{ 21, 22, 23, 24}
};
//define array of 2 pointers that point to the first
//rows of arr1 and arr2
int (*p[])[4] = { arr1, arr2 };
//use pointer array to get the 4th element in the
//3rd row of the second 2D array
printf( "%d\n", p[1][2][3] );
}
This program will give you the correct output 24.
If you find the declaration int (*p[])[4] hard to understand, then you may want to read this page on how these declarations are to be interpreted. Also, this site may be useful.
You can also simplify your declarations by using a typedef, so that the type arrow_row represents an array of 4 int elements (i.e. a row of a 2D array) like this:
typedef int array_row[4];
Now, you can simplify the declaration
int (*p[])[4] = { arr1, arr2 };
to:
array_row *p[] = { arr1, arr2 };
int *p[] is an array of pointers, not a pointer to an array.
You'll need to do:
int (*p)[3]= (int [][3]) { {1,2,3},{10,20,30} };
The reason why is that an array, whenever used in an expression, decays into a pointer to the first element. So no matter the array type, your pointer will need to correspond to the pointer to the first element.
In case of an int[], the element type is int and a pointer to it would be int*.
In case of an int[][3], the element type is int[3] and a pointer to it would be int (*p)[3].

Error assigning one int pointer to another, but not when working with arrays

This code works just fine:
int main() {
int arr1[4] = {5,1,1,5};
int* arr2 = arr1;
for (int i = 0; i < 4; ++i) {
printf("%d ", arr2[i]);
}
return 0;
}
But this one is either not running or giving me an unexpected output:
int main() {
int* arr1 = {5,1,1,5};
int* arr2 = arr1;
for (int i = 0; i < 4; ++i) {
printf("%d ", arr2[i]);
}
return 0;
}
Why is this?
(This one works too, where is the logic?)
int main() {
int arr1[] = {5,1,1,5};
int* arr2 = arr1;
for (int i = 0; i < 4; ++i) {
printf("%d ", arr2[i]);
}
return 0;
}
Although there are some ways in which you can switch between them, in C, pointers and arrays are not the same thing as one another. An array is a sequence of objects that are laid out one after the other. So, for example, you can have
int arr[] = { 3, 1, 4, 1, 5 };
and in memory this looks like
arr [ 3 ][ 1 ][ 4 ][ 1 ][ 5 ]
When you write int arr[] = { 3, 1, 4, 1, 5 };, C interprets this to mean "I'd like you to make me a new array of integers (int arr[]). And in particular, I'd like that array to hold the values 3, 1, 4, 1, and 5."
A pointer is an object that stores a location in memory. This is different than an array - an array is a sequence of values, and a pointer just says where to look to find something. What makes this confusing is that an array decays to a pointer, meaning that an array can be converted into a pointer to its first element. So if you write
int arr[] = { 3, 1, 4, 1, 5 };
int* ptr = arr;
then things look like this:
arr [ 3 ][ 1 ][ 4 ][ 1 ][ 5 ]
^
|
ptr ----+
Intuitively, you can think of the line int* ptr = arr; as meaning "please make ptr point to the first element of the array named arr."
However, array-to-pointer decay only works if you have an actual array object to work with. If you write
int* ptr = { 3, 1, 4, 1, 5 };
the C compiler does not interpret this to mean "make ptr point to an array containing 3, 1, 4, 1, and 5." Rather, it thinks you're saying
Please initialize ptr to the number 3 (oops, 3 isn't a pointer, so now your pointer isn't pointing to an array at all and is instead looking randomly in memory),
and, by the way, when you're initializing it, I'd also like you to initialize it with the numbers 1, 4, 1, and 5 (oops, we don't know what to do with those).
This will generate a lot of compiler warnings (thanks to #yano for putting this together), indicating that the C compiler is worried that what you're telling it to do isn't what you meant.
There's no deep, fundamental reason why C couldn't have been designed so that the line
int* ptr = { 3, 1, 4, 1, 5 };
would mean "make ptr point to an array of five elements," but that's just not how the language works.
The general rule of thumb here is
you can initialize an array by setting it equal to a brace-enclosed list holding the values of the array,
you can initialize a pointer to point to the first element of an array by assigning it an existing array, but
you cannot initialize a pointer to point at a brace-enclosed list of values that you want interpreted as an array.
Hope this helps!

Initializing "a pointer to an array of integers"

int (*a)[5];
How can we Initialize a pointer to an array of 5 integers shown above.
Is the below expression correct ?
int (*a)[3]={11,2,3,5,6};
Suppose you have an array of int of length 5 e.g.
int x[5];
Then you can do a = &x;
int x[5] = {1};
int (*a)[5] = &x;
To access elements of array you: (*a)[i] (== (*(&x))[i]== (*&x)[i] == x[i]) parenthesis needed because precedence of [] operator is higher then *. (one common mistake can be doing *a[i] to access elements of array).
Understand what you asked in question is an compilation time error:
int (*a)[3] = {11, 2, 3, 5, 6};
It is not correct and a type mismatch too, because {11,2,3,5,6} can be assigned to int a[5]; and you are assigning to int (*a)[3].
Additionally,
You can do something like for one dimensional:
int *why = (int p[2]) {1,2};
Similarly, for two dimensional try this(thanks #caf):
int (*a)[5] = (int p[][5]){ { 1, 2, 3, 4, 5 } , { 6, 7, 8, 9, 10 } };
{11,2,3,5,6} is an initializer list, it is not an array, so you can't point at it. An array pointer needs to point at an array, that has a valid memory location. If the array is a named variable or just a chunk of allocated memory doesn't matter.
It all boils down to the type of array you need. There are various ways to declare arrays in C, depending on purpose:
// plain array, fixed size, can be allocated in any scope
int array[5] = {11,2,3,5,6};
int (*a)[5] = &array;
// compound literal, fixed size, can be allocated in any scope
int (*b)[5] = &(int[5]){11,2,3,5,6};
// dynamically allocated array, variable size possible
int (*c)[n] = malloc( sizeof(int[n]) );
// variable-length array, variable size
int n = 5;
int vla[n];
memcpy( vla, something, sizeof(int[n]) ); // always initialized in run-time
int (*d)[n] = &vla;
int a1[5] = {1, 2, 3, 4, 5};
int (*a)[5] = &a1;
int vals[] = {1, 2};
int (*arr)[sizeof(vals)/sizeof(vals[0])] = &vals;
and then you access the content of the array as in:
(*arr)[0] = ...

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.]

Resources