Declaration of an array without highest dimension - c

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.

Related

What is each curly brace standing for when declaring/initializing a struct? (warning: missing braces around initializer [-Wmissing-braces])

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

How to declare a jagged array in a header file?

To define a jagged array, I'm using this answer by #FaisalVasi. This works perfectly. To get the (i,j)-entry of a such defined array, type (*jagged[i])[j].
However, I like to put all my arrays in a separate file (my constant arrays), and then I have to declare them in the header file. And I don't manage to do that. I tried **jagged = unsigned[][] and *jagged = unsigned*[], and other attempts I don't remember. Anyway everything I've tried did not work. So how should I declare the jagged array in the header file?
I'm a novice in C and I hope the question is clear. Otherwise please ask me what could I clarify.
NOTE: Deviating from the requested array-of-pointers-to-rows syntax and pointing to the rows directly in the array, as proposed by #Someprogrammerdude, allows to obtain the same result, but with one less indirection and with a more clear access syntax.
direct array of rows solution
definition
unsigned jagged_row0[] = { 0, 1, 99 };
unsigned jagged_row1[] = { 1, 2, 3, 4, 5, 6, 99 };
unsigned *jagged[] = (unsigned *[]){ jagged_row0, jagged_row1 };
or in general:
type jagged_row0[] = { ... };
type jagged_row1[] = { ... };
...
type *jagged[] = (type *[]){ jagged_row0, jagged_row1, ... };
declaration
extern unsigned *jagged[];
or in general:
extern type *jagged[];
usage
unsigned v_i_j = jagged[i][j];
or in general:
type v_i_j = jagged[i][j];
original answer
The following solution addresses the definition given in the cited answer by #FaisalVasi, where the jagged array stores explicit pointers to the jagged rows.
definition (in some .c file)
unsigned jagged_row0[] = {0,1};
unsigned jagged_row1[] = {1,2,3};
unsigned (*jagged[])[] = { &jagged_row0, &jagged_row1 }; /* note the ampersand */
/* or alternatively, since compound literals are lvalues ... */
unsigned (*jagged[])[] = { &(int[]){0,1}, &(int[]){1,2,3} };
declaration
extern unsigned (*jagged[])[];
usage
unsigned *jagged_row;
...
jagged_row = *jagged[i];
unsigned v_i_j = jagged_row[j]; /* value at [i][j] */
or more compactly:
unsigned v_i_j = (*jagged[i])[j]; /* value at [i][j] */
explanation
A jagged row is an array of some basic type, in our case an array (of length determined by the static initialization) of unsigned (unsigned[]), which can be thought of, with some caveats, as a pointer to unsigned (unsigned *).
With the proposed definition, the jagged array is an array of pointers to jagged rows, which, with the same simplification, can be though of as an array of unsigned **.
When you index the first dimension, you are getting the pointer to the jagged row (an array), then you have to dereference this pointer to get to the array itself that is the jagged row, than you have to index this array to get to the final value.
A jagged array in C is usually a pointer to the first element of an array of pointers. Basically a pointer to a pointer. I.e. type **jagged.
To declare just about any variable in a header file use the extern keyword. As in
extern type **jagged;
[Replace type with the actual type]
There's two way to use it:
Full dynamic allocation
jagged = malloc(sizeof(*jagged) * M);
for (unsigned i = 0; i < M; ++i)
jagged[i] = calloc(N, sizeof(**jagged));
// Now jagged is a MxN jagged matrix where each element is zero
jagged[1][2] = 1; // Sets a single value to 1
Arrays of arrays
type jagged_row_0[] = { a, b, c };
type jagged_row_1[] = { x, y };
type **jagged = (type *[2]){ jagged_row_0, jagged_row_1 };
printf("jagged[1][0] = %d\n", jagged[1][0]);
Of course, you could make an actual array of array of pointers instead (much like the second case above):
extern type *jagged[];
...
type *jagged[] = { jagged_row_0, jagged_row_1 };
...
printf("jagged[1][0] = %d\n", jagged[1][0]);
Be very careful when having rows with different size though, so you don't go out of bounds.

What is a designated initializer in C?

I have an assignment that requires me to understand what are designated initializers in C, and what it means to initialize a variable with one.
I am not familiar with the term and couldn't find any conclusive definitions.
What is a designated initializer in C?
Designated initialisers come in two flavours:
1) It provides a quick way of initialising specific elements in an array:
int foo[10] = { [3] = 1, [5] = 2 };
will set all elements to foo to 0, other than index 3 which will be set to 1 and index 5 which will be set to 2.
2) It provides a way of explicitly initialising struct members. For example, for
struct Foo { int a, b; };
you can write
struct Foo foo { .a = 1, .b = 2 };
Note that in this case, members that are not explicitly initialised are initialised as if the instance had static duration.
Both are standard C, but note that C++ does not support either (as constructors can do the job in that language.)
The Designed Initializer came up since the ISO C99 and is a different and more dynamic way to initialize in C when initializing struct, union or an array.
The biggest difference to standard initialization is that you don't have to declare the elements in a fixed order and you can also omit element.
From The GNU Guide:
Standard C90 requires the elements of an initializer to appear in a fixed order, the same as the order of the elements in the array or structure being initialized.
In ISO C99 you can give the elements in random order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in C90 mode as well
Examples
1. Array Index
Standard Initialization
int a[6] = { 0, 0, 15, 0, 29, 0 };
Designed Initialization
int a[6] = {[4] = 29, [2] = 15 }; // or
int a[6] = {[4]29 , [2]15 }; // or
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
2. Struct or union:
Standard Initialization
struct point { int x, y; };
Designed Initialization
struct point p = { .y = 2, .x = 3 }; or
struct point p = { y: 2, x: 3 };
3. Combine naming elements with ordinary C initialization of successive elements:
Standard Initialization
int a[6] = { 0, v1, v2, 0, v4, 0 };
Designed Initialization
int a[6] = { [1] = v1, v2, [4] = v4 };
4. Others:
Labeling the elements of an array initializer
int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
write a series of ‘.fieldname’ and ‘[index]’ designators before an ‘=’ to specify a nested subobject to initialize
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };
Guides
designated-initializers-c | geeksforgeeks.org
using-designated-initializers
tutorialspoint.com | designated-initializers-in-c

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

1D and 2D array initialization with braces

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.

Resources