The following code gives an "invalid initializer" error:
int a[]=(1,2,3);
But the following compiles successfully although it considers ',' as comma OPERATOR and not SEPARATOR:
int a[][2]={(1,2),(3,4)};
So why is () invalid for a 1D array and not for a 2D array?
In the first example:
int a[]=(1,2,3);
the initializer is a (rather odd) expression of type int. (It contains two comma operators, and yields the value 3.) The object is an array. The initialization is invalid because it's a type mismatch.
The second:
int a[][2]={(1,2),(3,4)};
is equivalent to:
int a[][2] = { 2, 4 };
which is valid because it's permissible to omit nested curly braces in an initializer; elements are used to initialize successive elements of the object. The first and third commas are comma operators; the second is a delimiter.
The outermost curly braces are optional if the initializer is simply an expression of the target type, whether it's a scalar, struct, or union. For example, you can write:
int x = 42;
int y = { 42 };
The outermost curly braces are required for an initializer that specifies element values (for an array, struct, or union object).
For example:
struct foo {
int x;
int y;
};
struct foo arr[2] = { 1, 2, 3, 4 };
is valid -- but it's more clearly written as:
struct foo arr[2] = { { 1, 2 }, { 3, 4 } };
Apart from the first example being invalid, both are poor style. The first may have been intended to be:
int a[] = { 1, 2, 3 };
and the second either:
int a[][2] = { 2, 4 };
or
int a[][2] = {{1, 2}, {3, 4}};
depending on the intent.
You forgot the curly braces in the first example. The accolades (curly braces) denote the initialisation of the contents of the array, the contents are then handled by your declarations within those accolades. Basically you're not initialisating the array in the first example. The parenthesis denote the order of evaluation, not arguments as they do with functions.
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.
I came across the following structure:
static struct {
unsigned char a[5];
} b[] = {
{1,1,1,1,1},
{2,2,2,2,2}
};
However, if it is being compiled I get the following warning "warning: missing braces around initializer [-Wmissing-braces]".
If I alter it like so:
static struct {
unsigned char a[5];
} b[] = {
{{1,1,1,1,1}},
{{2,2,2,2,2}}
};
Then the warning is gone. What is each curly brace standing for after "b[] = " ?
The innermost curly braces are obviously? standing for the initialization of char a[5]. But what are the other braces standing for? Obviously? one of the other curly braces has to account for the structure array b[] but which one? And why is there, as it seems, a third curly brace neccessary and what is it standing for? This confuses me.
int a[2] = { 1, 2 };
Ok. Now this:
int a[2][2] = { { 1, 2 } , { 3, 4 } };
Right? a[0][0] = 1 and a[0][1] = 2 and a[1][0] = 3 and a[1][1] = 4. a[0] is memcmp equal to (int[]){ 1, 2 } and a[1] is memcmp equal to (int[]){ 3, 4 }.
Now this:
struct {
int a[2];
} b = { { 1, 2 } };
So the first { } stand for structure initialization and the inner stand for b.a initialization. Now we make an array of structures:
struct b_s {
int a[2];
} b[] = {
{
{ 1, 2 },
},{
{ 3, 4, }
},
};
So the first braces stand for array b[] initialization. The second one are for structure b[0] to initialize. The third one are to initialize the b[0].a array.
The b[0] is memcmp equal to &(struct b_s){ {1, 2 } }. The b[0].a is memcmp equal to (int[2]){ 1, 2 }. The b[0].a[0] is equal to 1.
Each brace corresponds to the start of a subobject (an object inside an aggregate object, such as an array or structure).
b[] is an array, so the first brace introduces elements of the array.
Each b is a structure, so the next brace introduces members of the structure.
The member a inside b is an array, so the next braces introduces elements of that array.
{1,1,1,1,1} - The five elements of an array.
{{1,1,1,1,1}} - That's how you initialize a struct with a field which is an array of five ints in this case.
{{{1,1,1,1,1}}, {{2,2,2,2,2}}} - This is an array of two elements. Where each element is an instance of a struct as mentioned above.
You have an array of structs containing arrays. Three pairs of braces.
static struct {
unsigned char a[5];
} b[] = { // array b
{ // struct
{ // array a
1,1,1,1,1}},
{ // another struct
{2,2,2,2,2}}
};
Sorry for asking the already answered question, I am a newbie to C and don't understand the solutions.
Here is my function
int rotateArr(int *arr) {
int D[4][4];
int i = 0, n =0;
for(i; i < M; i ++ ){
for(n; n < N; n++){
D[i][n] = arr[n][M - i + 1];
}
}
return D;
}
It throws an error
main.c|23|error: subscripted value is neither array nor
pointer nor vector|
on line
D[i][n] = arr[n][M - i + 1];
What's wrong? I am just setting the value of an array element to another array element.
The arr passed is declared as
int S[4][4] = { { 1, 4, 10, 3 }, { 0, 6, 3, 8 }, { 7, 10 ,8, 5 }, { 9, 5, 11, 2} };
C lets you use the subscript operator [] on arrays and on pointers. When you use this operator on a pointer, the resultant type is the type to which the pointer points to. For example, if you apply [] to int*, the result would be an int.
That is precisely what's going on: you are passing int*, which corresponds to a vector of integers. Using subscript on it once makes it int, so you cannot apply the second subscript to it.
It appears from your code that arr should be a 2-D array. If it is implemented as a "jagged" array (i.e. an array of pointers) then the parameter type should be int **.
Moreover, it appears that you are trying to return a local array. In order to do that legally, you need to allocate the array dynamically, and return a pointer. However, a better approach would be declaring a special struct for your 4x4 matrix, and using it to wrap your fixed-size array, like this:
// This type wraps your 4x4 matrix
typedef struct {
int arr[4][4];
} FourByFour;
// Now rotate(m) can use FourByFour as a type
FourByFour rotate(FourByFour m) {
FourByFour D;
for(int i = 0; i < 4; i ++ ){
for(int n = 0; n < 4; n++){
D.arr[i][n] = m.arr[n][3 - i];
}
}
return D;
}
// Here is a demo of your rotate(m) in action:
int main(void) {
FourByFour S = {.arr = {
{ 1, 4, 10, 3 },
{ 0, 6, 3, 8 },
{ 7, 10 ,8, 5 },
{ 9, 5, 11, 2}
} };
FourByFour r = rotate(S);
for(int i=0; i < 4; i ++ ){
for(int n=0; n < 4; n++){
printf("%d ", r.arr[i][n]);
}
printf("\n");
}
return 0;
}
This prints the following:
3 8 5 2
10 3 8 11
4 6 10 5
1 0 7 9
You are not passing your 2D array correctly. This should work for you
int rotateArr(int *arr[])
or
int rotateArr(int **arr)
or
int rotateArr(int arr[][N])
Rather than returning the array pass the target array as argument. See John Bode's answer.
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" is converted ("decays") to an expression of type "pointer to T", and the value of the expression is the address of the first element of the array.
If the declaration of the array being passed is
int S[4][4] = {...};
then when you write
rotateArr( S );
the expression S has type "4-element array of 4-element array of int"; since S is not the operand of the sizeof or unary & operators, it will be converted to an expression of type "pointer to 4-element array of int", or int (*)[4], and this pointer value is what actually gets passed to rotateArr. So your function prototype needs to be one of the following:
T rotateArr( int (*arr)[4] )
or
T rotateArr( int arr[][4] )
or even
T rotateArr( int arr[4][4] )
In the context of a function parameter list, declarations of the form T a[N] and T a[] are interpreted as T *a; all three declare a as a pointer to T.
You're probably wondering why I changed the return type from int to T. As written, you're trying to return a value of type "4-element array of 4-element array of int"; unfortunately, you can't do that. C functions cannot return array types, nor can you assign array types. IOW, you can't write something like:
int a[N], b[N];
...
b = a; // not allowed
a = f(); // not allowed either
Functions can return pointers to arrays, but that's not what you want here. D will cease to exist once the function returns, so any pointer you return will be invalid.
If you want to assign the results of the rotated array to a different array, then you'll have to pass the target array as a parameter to the function:
void rotateArr( int (*dst)[4], int (*src)[4] )
{
...
dst[i][n] = src[n][M - i + 1];
...
}
And call it as
int S[4][4] = {...};
int D[4][4];
rotateArr( D, S );
The problem is that arr is not (declared as) a 2D array, and you are treating it as if it were 2D.
You have "int* arr" so "arr[n]" is an int, right? Then your "[M - 1 + 1]" bit is trying to use that int as an array/pointer/vector.
the second subscript operator is invalid here.
You passed a int * pointer into function, which is a 1-d array. So only one subscript operator can be used on it.
Solution : you can pass int ** pointer into funciton
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.
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.]