Related
Struct initializes can be used after initialization by casting it. Eg.
struct EST {
int a;
float b;
}est;
int main() {
est = (struct EST){23, 45.4}; //This works nicely and est gets the values
printf("a: %d\nb: %f\n", est.a, est.b);
}
But the same can't be done for arrays:
int arr[6];
arr = (int []){1, 2, 3, 4, 5};
This gives
error: assignment to expression with array type
What's more head breaking is that if there is an array in the struct, it still works.
struct Weird {
int arr[6];
}w;
int main() {
w = (struct Weird){{1, 2, 3, 4, 5}}; /* It works. The member arr gets all its elements
filled
*/
}
There seems to be something about the = operator not being valid with arrays after initializing. That is my theory.
Why is this and how can arrays be assigned after initializing?
initialization means initializing of a variable at declaration time. The following is correct and is supported by 'c':
int arr[6] = {1,2,3,4,5,6};
Assignment means assigning a value to a variable somwhere in the program after initialization. 'C' does not support assignment to a whole array. Arrays are very special members in 'c' and are treated in a special way which does not allow assignments.
However, you can always copy one array into another either by using a for loop or my using something like memcpy. Here is an example:
int arr[6], brr[6] = {1,2,3,4,5,6};
memcpy(arr,(int[6]){1,2,3,4,5},sizeof(int[6]));
BTW, the cast-like object from your example (int[]){1,2,3,4,5} is called 'compound literal' and is also allowed in c. Here it is used to initialize the parameter of the memcpy function.
int array[2] = {1, 1};
int (*pointer_array)[2] = {NULL, NULL};
The first line can be correctly compiled but not the second one? Why?
GCC compiler will pop up a warning, excess elements in scalar initializer.
How to initialize a pointer array in C?
EDITED
I declared a pointer array in a wrong way.
It should be like this:
int *pointer_array[2] = {NULL, NULL};
It should be
int (*pointer_array)[2]=(int[]){1,2};
This is pointer to array of int .I don't know you want pointer to array of int or array of pointers.
To declare as array of pointer you need to do this -
int *pointer_array[2];
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 a 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[2]) {1,2};
Similarly, for two dimensional try this(thanks #caf):
int (*a)[5] = (int [][5]){ { 1, 2, 3, 4, 5 } , { 6, 7, 8, 9, 10 } };
we all know that to define a 2-D array of strings we do
char *c[5] = {"string1", "string2", "string3", "string4", "string5"};
or
char c1[][10] = {"string1", "string2", "string3", "string4", "string5"};
and when i get the value of one of these,we do `printf("%c ",c[1][0] ); //just example
but when declaring
int a[][3]={{20,60,30},{40,90,180},{200,880,900}}; //no problem with getting the output from
but when declaring
int (*a1)[3]={{20,60,30},{40,90,180},{200,880,900}};
and trying to get the output printf("%i",a1[0][0]);
the program is crash
i know that from the definition of (a) i can do as following
int(*p)[3]=a; then printf("%i",p[0][0]);
and i also know if i do int *a1[3] then i create an array of pointers ,and to avoid that we put the parentheses,so why with the definition of int(*a1)[3] the program crash ? and how the compiler deal with it ? and what the difference between this case and the case of string char *c[5] it the same if i put char (*c)[5]and no problems happens with char ?
In the declaration
int (*a1)[3]={{20,60,30},{40,90,180},{200,880,900}};
a1 is a pointer (to an array of 3 ints). You can't initialize it with the above initializer. You can understand this by taking an example
int a[] = {1, 2, 3};
int *p = a;
You can't initialize p as
int *p = {1, 2, 3};
because p is a pointer, not arrays. That said pointers are not arrays.
You should note that the declaration
char *c[5] = {"string1", "string2", "string3", "string4", "string5"};
and
char c1[][5] = {"string1", "string2", "string3", "string4", "string5"};
are completely different with each other.
Former declares c as an array of 5 pointers to char while latter declares c1 an array of arrays of chars.
First of all this declaration
char *c[5] = {"string1", "string2", "string3", "string4", "string5"};
does not declare a 2D array. It is a one-dimensional array of pointers to string literals.
This declaration
char c1[][10] = {"string1", "string2", "string3", "string4", "string5"};
is indeed a declaration of a 2D array.
This declaration
int (*a1)[3]={{20,60,30},{40,90,180},{200,880,900}};
is invalid and the compiler should issue a diagnostic message. In this declaration a1 is a scalar object and it may not be initialized by a list of initializers in braces when there are more than one initializer and moreover when there are enclosed initializers in braces.
A scalar object may be initialized by the brace list containing only one initializer as for example
int x = { 10 };
According to the C Standard (6.7.9 Initialization)
11 The initializer for a scalar shall be a single expression,
optionally enclosed in braces.
But you can do the following using compound literals
#include <stdio.h>
int main( void )
{
int ( *a1 )[3] = ( int[][3] )
{
{ 20, 60, 30 },
{ 40, 90, 180 },
{ 200, 880, 900 }
};
for ( size_t i = 0; i < 3; i++ )
{
for ( size_t j = 0; j < 3; j++ ) printf( "%d ", a1[i][j] );
printf( "\n" );
}
}
The program output is
20 60 30
40 90 180
200 880 900
In this program declaration int ( *a1 )[3] declares a pointer to an array of type int[3] . That is in the right side of the declaration there is a compound literal that has type int [3][3] (a 2D array) that is implicitly converted to a pointer to its first element and this value is assigned to a1
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] = ...
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.]