This question already has answers here:
Using non standard declaration of array in C
(2 answers)
Closed 6 years ago.
Here is one not-so-common way of initializing the array:
int a[3] = {[2] 5, [0] 10, [1] 15};
Used this array in the program,
#include <stdio.h>
int main() {
//code
int a[3] = {[2] 5, [0] 10, [1] 15};
printf("a[0] = %d a[1] = %d a[2] = %d\n", a[0], a[1], a[2]);
return 0;
}
Output:
a[0] = 10 a[1] = 15 a[2] = 5
Online Compiler Link:
http://code.geeksforgeeks.org/4onQAI
So, I have a question:
Is it the correct way to initialize array?
Close. The correct way is as follows:
int a[3] = {[2] = 5, [0] = 10, [1] = 15};
This is a designated initializer, which allows you to initialize specified elements. Any elements not specified are set to 0.
This is specified in section 6.7.9 of the C standard.
The syntax you show is a non-standard extension supported by some compilers, specifically GCC. If you were to compile with -pedantic, you would get the following warning:
warning: obsolete use of designated initializer without ‘=’
Your code snippet uses an obsolete syntax for this designated initializer:
int a[3] = {[2] = 5, [0] = 10, [1] = 15};
An alternative syntax for this that has been obsolete since GCC 2.5 but GCC still accepts is to write ‘[index]’ before the element value, with no ‘=’. (reference)
Omitting = is not standard, and should not be used for new development.
The correct way to use designated initializer is
int a[3] = {[2] = 5, [0] = 10, [1] = 15};
There should be = between the [index] and the value as per the C standard.
The way you are initialising may the some extension.
Grammer for initializations(C11-§6.7.9)
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designationopt initializer
initializer-list , designationopt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
Related
I have the question if there is any way to initialize an array with multiple elements without brackets, for example:
int a[5] = {1,2,3,4,5};
Since *(a + 5) equals with a[5] , why i cannot initialize with:
int *(a + 5) = {1,2,3,4,5};
it gives me the error: expected ')' before '+' token.
The equivalence of E1[E2] and *(E1 + E2) only applies to an expression. What you have is a declaration which has different syntax rules.
So you need to use this syntax:
int a[5] = {1,2,3,4,5};
Replacing a[5] with *(a + 5) does not work in declarations or definitions.
If you really want to avoid square brackets (to win a bet I assume), here are 2 contorted but standard complying solutions:
Using trigraphs: int a??(5??) = {1,2,3,4,5};
Using digraphs: int a<:5:> = {1,2,3,4,5};
More information can be found in Digraphs and Trigraphs.
You can even write a fragment that will compile on recent compilers where trigraphs are disabled and digraphs supported:
// trick: the comment spans to the next line if trigraphs are enabled
#define TRIGRAPHS_DISABLED 1 //??/
-1
#if TRIGRAPHS_DISABLED
int a<:5:> = {1,2,3,4,5};
#else
int a??(5??) = {1,2,3,4,5};
#endif
This
int *(a + 5) = {1,2,3,4,5};
just is an invalid declaration because in the parentheses there is used the expression ( a + 5 ) with an entity named a that was not declared.
Without using square brackets you could write for example
typedef int T[5];
T a = { 1, 2, 3, 4, 5 };
As for this your statement
Since *(a + 5) equals with a[5] , why i cannot initialize with:
then in this context *( a + 5 ) is not an array. It is an expression that yields an element a[5] provided that a was already declared as an array with the number of elements not less than 6. Otherwise a[5] will be a non-existent element of the array a.
You may try like this:
int *arr=(int*)malloc(5*sizeof(int));
for(int i=0;i<5;i++) {
scanf("%d",&(*(arr+i)));
}
or
int *arr=(int*)malloc(5*sizeof(int));
*(arr+0)=1;
*(arr+1)=2;
*(arr+2)=3;
*(arr+3)=4;
*(arr+4)=5;
This question already has answers here:
Why do C and C++ support memberwise assignment of arrays within structs, but not generally?
(5 answers)
Closed 4 years ago.
I have a question about C syntax, how is it possible that this:
int a[ ][2] = { 1, 2, 3, 4 };
is legal why this is not:
int a[] = { 1, 2, 3, 4 };
int b[ ][2] = a;
or even:
int a[] = { 1, 2, 3, 4 };
int *b[2] = a;
is not legal.
What it is so hard from the pointer-math point of view that it cannot handle this by itself? Is it just a problem with the Grammar or the compilers can't infer the correct memory step-sizes?
gcc error:
main.c:14:19: error: invalid initializer
int b[ ][2] = a;
The explanation is very simple.
Two main reasons:
In the C you cant assign arrays.
The only complex types where assignment is allowed in C are structs and unions.
The initialization of the global variables requires constant expression.
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
In the following code a array is initialized with s "seed" variable, which is clearly not constant expression (as it's evaluated "run-time"):
#include <stdio.h>
int main(void)
{
int s = 1, i;
int a[] = {s, s + 2, s + 4, s + 6, s + 8};
for (i = 0; i < (int) (sizeof a / sizeof a[0]); i++)
printf("%d ", a[i]); /* prints: 1 3 5 7 9 */
putchar('\n');
return 0;
}
It compiles in gcc -Wall -Wextra with no warnings. However adding -pedantic provokes:
check.c: In function ‘main’:
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
Does C require constant expression for initializer elements ?
This is valid in c99 but not valid in c89 (emphasize mine):
(C89, 6.5.7) "All the expression in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions"
but
(C99, 6.7.8p4) "All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals."
By default, gcc compiles with -std=gnu89 which is c89 + GNU extensions.
In addition to ouah's excellent answer I would add that C99 requires constant expression for designators within designated initializers (only in C99), e.g. following array initialization is invalid in C99:
int s = 1, i = 0;
int a[] = {[i] = s, [i+1] = s + 2, [i+2] = s + 4, s + 6, s + 8};
which might be rewritten as e.g.:
#define I 0
int s = 1, i;
int a[] = {[I] = s, [I+1] = s + 2, [I+2] = s + 4, s + 6, s + 8};
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.]