C array of structs declaration - c

In the Linux kernel, I see a declaration of an array of structs that looks like this
struct SomeStructName [] ={
[SOMEWEIRD_NAME] = {
.field1 = "some value"
},
[SOMEWEIRD_NAME2] = {
.field1 = "some value1"
},
}
I have never seen a declaration like that, specifically I can't figure out what [SOMEWEIRD_NAME] means, and why it's used.

It's a C99 designated initializer for arrays.
For example:
/*
* Initialize element 0 to 1
* 1 to 2
* 2 to 3
* 255 to 1
* and all other elements to 0
*/
int arr[256] = {[0] = 1, 2, 3, [255] = 1};
It allows you to initialize some specific array elements in any order and also allows you to omit some elements.
In your example the expression between [] can be a macro name for an integer constant expression or an enum constant. It cannot be a variable name as it has to be an integer constant expression.

Im not sure what you meant but i assume SOMEWEIRD_NAME is a Define value.
Define is a way to give values another name but it wont take space in you'r memorry on runtime, insted, it will be replaced everywhere the name of that defined values is writen in your code during compiling prosses.
The syntax for deifne is as the following: #define NAME_OF_DEFINE 80
in the following example every NAME_OF_DEFINE in your code will be replaced whit the values 80. Notice that you shouldn't end the line whit ;.
In your example i expect SOMEWEIRD_NAME to have a numbric value to set the array's size.
You can fine more information about #define here

The "SOMEWEIRD_NAME" is most likely either a #define whose value is a number, or it's an enumeration, whose numeric value is its position in the enumeration.

Related

What do square brackets arround an enum mean? [enum_value] [duplicate]

This question already has answers here:
How to initialize only few elements of an array with some values?
(4 answers)
Closed 4 years ago.
I'm currently wrapping my head around proper state machines, and I've found this article which seemed to be exactly what I've been searching for:
https://aticleworld.com/state-machine-using-c/
In the process of understanding table of the table based state machine I've stumbled over this piece of code which in my opinion is quite hard to read.
So this is as far as I can come:
eSystemState is a typedefed enum which indicates the current state.
eSystemEvent is a typedefed enum which indicates the current event.
pfEventHandler is a typedefed function pointer returning eSystemState.
afEventHandler is a typedefed, two dimensional array (limited by "last_State" and "last_Event") of function pointers returning eSystemState.
Next up are some event handlers for each type of event.
Then beginning of main, some initialization and there it comes.
The previously defined type afEventHandler gets filled with content, but the operations which are used there are a big mystery to me.
I know that for every curly brackets a new 'row' gets filled, but what do the square brackets around the enums mean, and why can one apparently assign a value to whatever comes out of this?
I know that enums are essentially numbers, and I suspect it is some (to me) super obscure way to address a specific element in an array.
Am I wrong?
// Table to define valid states and event of finite state machine
static afEventHandler StateMachine = {
[Idle_State] ={[Card_Insert_Event]= InsertCardHandler },
[Card_Inserted_State] ={[Pin_Enter_Event] = EnterPinHandler },
[Pin_Eentered_State] ={[Option_Selection_Event] = OptionSelectionHandler},
[Option_Selected_State] ={[Amount_Enter_Event] = EnterAmountHandler},
[Amount_Entered_State] ={[Amount_Dispatch_Event] = AmountDispatchHandler},
};
This syntax is for a designated initializer. It allows you to initialize specific elements of an array.
The value in square brackets is the index of the array element to initialize. In this case it is an enum value, but itcould be any integer.
The square brackets mark array subscripts. The enum identifiers inside them are simply ordinary expressions, replaced by the enum values.
C allows you to initialize arrays using explicit subscripts, called designators. For example, this initialize A[1] to 4:
int A[3] = { [1] = 4 };
(The other elements default to zero.)
With a two-dimensional array, the syntax gets more complicated:
int B[3][4] =
{
[1] = { [3] = 7 }
};
That initializes B[1][3] to 7. That is the syntax you are seeing in the code you refer to. It then uses enum identifiers like Idle_State instead of the sample constants 1, 3, and 7 shown above.
I've found it myself, it's a "designated initializer" which indeed specifies which element shall be set by a chosen value.
It's been introduced in C99 which explains why i didn't know about it. Other elements get initialized to 0.
I'll leave the question here for others who may wonder about the same.
How to initialize only few elements of an array with some values?
int a[10][10] = {
{},
{[5] = 8}
};
Means that in the second row the element 5 is gonna be initialized to eight, others will be zero.

Using non standard declaration of array in C

I came across the following code which declares char * array in C in a non-standard way:
/* Message Type description array */
char *msgType[M_LAST_MSG] =
{
[M_INIT_MSG] "Init",
[M_RESET_MSG] "Serdes Reset"
};
M_INIT_MSG, M_RESET_MSG and M_LAST_MSG are enumerations with corresponding values of 0, 1 and 2.
According to the formal C documentations, the variables inside this array are string (literals) so what is the purpose of using those enumerations in that manner and is there any documentation to back it up?
Compiled with ARM gcc compiler gcc-arm-none-eabi.
This syntax allows you to initialize specific elements of an array by index. You can use either int or enum values to specify which array element to initialize. This way, the values you assign don't need to be consecutive.
If for example you had this:
int x[5] = { [2] 3, [4] 7 };
It would be equivalent to this:
int x[5] = { 0, 0, 3, 0, 7 };
In the above example, the enum values specify that elements 0 and 1 of the array are initialized to "Init" and "Serdes Reset".
From section 6.7.8 of the C99 standard:
18 Each designator list begins its description with the
current object associated with the closest surrounding brace
pair. Each item in the designator list (in order) specifies
a particular member of its current object and changes the
current object for the next designator (if any) to be that member.
The current object that results at the end of the designator list is
the subobject to be initialized by the following initializer.
33 EXAMPLE 9 Arrays can be initialized to correspond to the
elements of an enumeration by using designators:
enum { member_one, member_two };
const char *nm[] = {
[member_two] = "member two",
[member_one] = "member one",
};
EDIT:
Note that the syntax from the standard includes a = while OP's example does not. The syntax without = is apparently an old syntax supported by GCC. Compiling OP's example gives the following warning:
warning: obsolete use of designated initializer without ‘=’
The GCC documentation states the following:
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 ‘=’.
That's a GNU extension. It was standardized in C99 with slightly different syntax, namely an equal sign between the [index] and the value and no way to specify a range of indices. They are called designated initializers.
The C standard shows an example of probably the most widespread use, provide a string description for enums:
33 EXAMPLE 9 Arrays can be initialized to correspond to the elements of an enumeration by using designators:
enum { member_one, member_two };
const char *nm[] = {
[member_two] = "member two",
[member_one] = "member one",
};
It even allows nifty stuff like
EXAMPLE 11 Designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood:
struct { int a[3], b; } w[] =
{ [0].a = {1}, [1].a[0] = 2 };

Initialize an array of structs in C or C99 to all the same values [duplicate]

This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
c structure array initializing
(5 answers)
Closed 6 years ago.
Lets assume the following in C or C99:
typedef struct
{
int x;
double y;
} MY_S;
MY_S a[666] = {333, 666.6};
Does this initialize the first object of the array only? If yes, is there a way to initialize ALL elements of the array to all the same values using that syntax (without calling a function/loop and without repeating the initializer)?
In standard C, you'd need to repeat the initializer. In GCC, you can specify a range of elements to initialize with the same initializer, for example:
MY_S a[666] = { [0 ... 665] = {333, 666.0} };
Quote from C99 standard section 6.7.8:
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.e. Only the first element will be initialized to the supplied value while the others will be filled with zeros.
There is no way (in standard C) other than a loop to initialize an array of complex structs (memset() can be used to initialize a block of memory with a specified value).
If I understood you correctly, you need to take a look at designated initializers designated initializers
This is a GNU C extension with which you can initialize values of an array in one show.
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
This will initialize 1 to elements 0 to 9, 2 to elements 10 to 99, 3 to 100th element.
And in your case, it is like
MY_S a[666] = { [0 .. 665] = {333, 666.0} };
This will initialize the first struct, and everything else is zeroed.
See ANSI C89 3.5.7 Initialization:
[...]
float z[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } };
initializes the first column of z as specified and initializes the rest with zeros.
[...]
There is, unfortunately, no way to initialize the array without looping over it, calling memset or by any other means.

Difference between literal constant & normal variable?

I am learning C programming, and my book says that unlike variables, constants cannot be changed during the program's execution. And that their are two types of constants Literal and Symbolic. I think that I understand Symbolic pretty well. But Literal Constants are confusing me.
The example it gave me for was
int count = 20;
I wrote this simple program, and I could change the value of the Literal Constant.
/* Demonstrates variables and constants */
#include <stdio.h>
/* Trying to figure out if literal constants are any different from variables */
int testing = 22;
int main( void )
{
/* Print testing before changing the value */
printf("\nYour int testing has a value of %d", testing);
/* Try to change the value of testing */
testing = 212345;
/* Print testing after changing the value */
printf("\nYour int testing has a value of %d", testing);
return 0;
}
It outputted this:
Your int testing has a value of 22
Your int testing has a value of 212345
RUN SUCCESSFUL (total time: 32ms)
Can someone explain how this happens, am I declaring it wrong? Or is there any difference between normal variable and literal constants?
-Thanks
The literal constant is the 20. You can change the value of count, but you cannot change the value of 20 to be, for example, 19.
(As some trivia, there are versions of FORTRAN where you could do exactly this, so it's not meaningless to talk about)
The literal in this case is the number 22 (and later the number 212345). You assign this literal to a variable testing. This variable can be changed.
This is a little trickier when it comes to strings and string literals. If you have a pointer to a string literal, you can change the actual pointer to point to some other string, but you can change what the original pointer points to.
For example:
const char *string_pointer = "Foobar";
With the above definition, you can not do e.g. string_pointer[0] = 'L';, as that is an attempt to modify the literal string that the pointer points to.
Depending on context, a symbolic constant can be either a "variable" declared as const or a preprocessor macro.
A literal constant in C is just any number itself, e.g. your 20. You cannot change it by doing, say, 20 = 50;. That is illegal.
There are also constant variables, e.g. const int blah = 42;. You cannot change this blah by doing something like blah = 100;.
But if you have a normal, non-constant variable, e.g. int foo = 123;, you can change it, e.g. foo = 456;.

enum is constant or const varibale or anything else ? getting error in the following code

#include<stdio.h>
typedef enum {a,b,c}key;
int main()
{
key d=3;
printf("%p\n,&a);
printf("%p\n",&d);
printf("%d\t %d\t %d\t %d\n",a,b,c,d);
return 0;
}
When I try to get the address of either a or b or c
Compiler throws an error that lvalue required for unary &
I didn't get it because it's working for d of same type.
What's happening here ? are these constants or the const varibales assigned with values 0 1 and 2 by the compiler.
Beacause this kind of error we got for constants only.
Please help , I am new to C
Check out what an enum really is. It's a value. Remember if you don't initialize an enum list the first one is given the value of 0.
Consider the boolean enum example:
typedef enum /* Declares an enumeration data type called BOOLEAN */
{
false, /* false = 0, true = 1 */
true
}BOOLEAN ;
So the enum "false" is 0. You can't take the address of 0, but if you make a "BOOLEAN" from this:
BOOLEAN something = false;
Now something is a variable and you can take the address of that.
a,b,c are symbols for constant-integers within an enum. They're not variables to have an address. Hence & cannot be used here(which means only rvalue).
The members of enums are constants (just like 3, 1000, or 'b'), hence can only be used as rvalues. They don't have any locations in memory.
But d is a variable whose value is one of enum members (not necessarily though). d has a well defined memory location and can be used as lvalue (we can take it's address, modify it etc).
An enum is just like an integer type, with the added bonus of having a bunch of named literals. An enumeration comprises a set of named integer constant values.
From C standard C99. Section 6.7 Semantics, point 3:
for an enumeration constant or typedef name, is the (only) declaration of the
identifier.
so it just a declaration. no memory will be allocated.

Resources