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.
Related
In K&R C(2nd) 127p,
The main change made by the ANSI standard is to define structure assignment-structures may be copied and assigned to, passed to functions, and returned by functions. This has been supported by most compilers for many years, but the properties are now precisely defined. Automatic structures and arrays may now also be initialized.
What's the meaning of 'Automatic structures and arrays may now also be initialized.'? I read this.
And It's written at 261p(the part of appendix C. summary of changes)
Automatic structures, unions, and arrays may be initialized, albeit in a restricted way.
I got following code is not allowed in K&R C(1st).
int main()
{
int a[3] = { 1, 2, 3 };
struct { int a; char b; } x = { 1, 2 };
}
Could you explain then how were arrays and structures initialized in that time?It's a bit confusing where to focus, 'automatic' to 'global' or 'now be initialized' to 'couldn't be initialized'.
As far as I understand, that point of time initialization at the time of definition were not allowed for structure, union and array type variables which automatic storage. They would have to be assigned values, using separate assignment statements. Example:
For array, it'll be looping over elements and assigning one by one.
For structures, accessing members and assigning them.
I encounter the following piece of code, but I don't know why do it in this way. Could any one explain it to me?
char *MPIDI_CH3_Pkt_type_to_string[MPIDI_CH3_PKT_END_ALL+1] = {
[MPIDI_CH3_PKT_EAGER_SEND] = "MPIDI_CH3_PKT_EAGER_SEND",
[MPIDI_CH3_PKT_EAGER_SEND_CONTIG] = "MPIDI_CH3_PKT_EAGER_SEND_CONTIG",
};
Zack
This is just using designated initializers, as in the question Designated initializers and omitted elements. For example,
const char *foo[42] = {[1] = "hello", [2] = "world"};
The code given in the question appears to be a way of stringizing constants.
You have to declare an array of char * pointers. And you have two manifest constants -MPIDI_CH3_PKT_EAGER_SEND and MPIDI_CH3_PKT_EAGER_SEND_CONTIG - with some values that you are not supposed to "know". Now, you want to make elements with indices MPIDI_CH3_PKT_EAGER_SEND and MPIDI_CH3_PKT_EAGER_SEND_CONTIG to point to corresponding string literal values (and leave all other array elements as null pointers).
How can you do that?
In C89/90 you can do it by initializing everything to nulls first and then use assignment to set the proper elements to proper values
char *MPIDI_CH3_Pkt_type_to_string[MPIDI_CH3_PKT_END_ALL+1] = { 0 };
MPIDI_CH3_Pkt_type_to_string[MPIDI_CH3_PKT_EAGER_SEND] = "MPIDI_CH3_PKT_EAGER_SEND";
MPIDI_CH3_Pkt_type_to_string[MPIDI_CH3_PKT_EAGER_SEND_CONTIG] = "MPIDI_CH3_PKT_EAGER_SEND_CONTIG";
In C99 you can use designed initializer feature to do the same thing in the initializatiuon, as a one-liner, which is exactly what is done in your example.
So, the answer to your "why" question would be: because the language feature used in your declaration does exactly what the user wanted to do. There's no other answer.
P.S. The real "why" question here is why they are using char * pointers to point to string literals (instead of const char * pointers). That's a really big "why".
In the following example,I've illustrated this using two structures test1 and test2.The first has two elements-an integer array sized two,and a float element.The second structure has 3 elements,2 integers and one float.
I initialize two structure variables s1 and s2 for test1 as:
s1={{23,52},2.5},s2={21,19,3.6};
Both work fine even though for s2 I have taken out the braces that enclose the array elements.It works fine without warning and output is correct.But when I initialize 2 variables for test2 as follows:
v1={{23,52},2.5},v2={21,19,3.6};
I get incorrect output when I try to print out values of v1 and these are the warnings that I had got upon compilation:
warning: braces around scalar initializer|
warning: (near initialization for 'v1.list1')|
warning: excess elements in scalar initializer|
warning: (near initialization for 'v1.list1')|
||=== Build finished: 0 errors, 4 warnings ===|
Based on this premise,please clear the following doubt that arise:
Question: If using v1={{23,52},2.5} instead of v1={23,52,2.5} confuses the compiler about whether the first 2 numbers are distinct integer elements of the structure or part of an integer array element of the structure,then why doesn't using s2={21,19,3.6} instead of s2={{21,19},3.6} confuse the compiler into thinking that the structure varialbe s2 has 3 elements (2 integer elements and one float),instead of 2 elements (one integer array of size 2 and a float)?What I especially want to understand is why is the first case about v1's initialization wrong.
#include<stdio.h>
struct test1{
int list[2];
float rate;
}s1={{23,52},2.5},s2={21,19,3.6}; //Works fine
struct test2{
int list1;
int list2;
float rate;
}v1={{23,52},2.5},v2={21,19,3.6}; //Messes things up
int main(void)
{
printf("%d,%d,%f\n",s1.list[1],s2.list[1],s2.rate);
printf("%d,%d,%f\n",v1.list1,v1.list2,v1.rate);
}
This is just a consequence of how the rules for initialisers are defined. If the current object of the initialisation is a struct, union or array, then if the next initialiser begins with a { then the initialisers enclosed by that brace and its matching } are used to initialise the members of that object; otherwise, it just marches through the list of initialisers, taking as many as it needs.
So, in the first case s1={{23,52},2.5}, the current object starts out as s1.list. This is an array, and the next initialiser is { 23, 52 }, so that's used to initialise the array. s1.rate is now the current object, and the next initialiser is 2.5, so that works as expected.
In the second case s2={21,19,3.6}, the current object starts out as s2.list. This is an array, but the next initialiser does not start out with { - so it takes as many values as it needs (in this case, two), and initialises the array with 21 and 19. s2.rate is now the current object, and the next initialiser is 2.5, so again that works as expected.
In the third case v1={{23,52},2.5}, the current object starts out as v1.list1. This is a scalar, and the corresponding initialiser is {23, 52}. This violates a constraint of the language - "The initializer for a scalar shall be a single expression, optionally enclosed in braces" - so that's why you get a warning. Formally the behaviour of your program is undefined, but it appears that your compiler just uses the first value contained in the initialiser and discards the excess ones. The current object is now v1.list2, and the next initialiser is 2.5, so the wrong value is used to initialise this member. There is no initialiser for v1.rate; since v1 has static storage duration, this member is initialiser to 0.0.
In the forth case v2={21,19,3.6}, the current object starts out as v1.list1, and the next initialiser is 21 - this value is used to initialise the member. After this the current object is v1.list2 and the next initialiser is 19; then v1.rate is the current object and the next initialiser is 3.6.
For minimum confusion, you should always use a brace-enclosed initialiser for each struct or array subobject.
In the case of the variable s2, the compiler knows the size of the embedded array, so it can properly assign to it even without the bracers. you might however get a warning that suggests you to use bracers, and if you don't then I suggest you enable more compiler warnings (it's good to fix warnings, as they might indicate errors that might be valid C but invalid logic).
In the case v1, you can't use extra bracers because there is no compound data type (structure/union/array). The bracers {} can only be used to initialize compound data types.
I'm looking through the "Processor Modeling Guide" provided by a company named OVP (a product similar to qemu). In it, there's a little code snippet resembling the following:
static or1kDispatchTableC dispatchTable = {
// handle arithmetic instructions
[OR1K_IT_ADDI] = disDefault,
[OR1K_IT_ADDIC] = disDefault,
[OR1K_IT_ANDI] = disDefault,
[OR1K_IT_ORI] = disDefault,
[OR1K_IT_XORI] = disDefault,
[OR1K_IT_MULI] = disDefault
};
I've never seen syntax like this before. irrelevant stuff about C++ removed
At the moment I don't have the ability to download/look at their stuff to look at how anything is defined, hence my question. If you recognize this syntax, can you weigh in?
edit
or1kDispatchTableC is a typedef for a pointer of type or1kDispatchTableCP, but I still don't have anything on what or1kDispatchTableCP is.
Well, assuming your first line is a typo, or or1kDispatchTableC is an array type, so that this is actually an array declaration, this looks like a C11 explicitly initialized array. The line
[OR1K_IT_ADDI] = disDefault,
initializes element OR1K_IT_ADDI to disDefault. Both of those need to be constant expressions -- OR1K_IT_ADDI is probably a #define or an enum tag.
I'm pretty sure that C++11 does NOT support this syntax, though some compilers (that also support C11) might support it as an extension.
From the names, I would guess that this is actually an array of function pointers.
This is called designated initializers and is a C feature (supported since C99). It allows addressing array and structure/union elements directly, filling the gaps with default values.
struct foo { int a[10]; };
struct foo f[] = { [5].a[3] = 20 };
Now this results in 5 elements of struct foo, all initialized to zero followed by a sixth element of struct foo with the 4th element of a initialized to 20.
Like someone else suspected, this is not supported by C++.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)
I want to pass an array to a function such that if I use the sizeof operator on array inside the function body, I should get the actual size of the array and not that of a pointer. For e.g -
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,0};
printf("Array size = %d\n", sizeof(arr)/sizeof(int)); ---> O/P = 40/4 = 10
func(arr);
}
void func(int arr[])
{
printf("Array size = %d\n", sizeof(arr)/sizeof(int)); --->O/P = 4/4 = 1
}
The printf statement in the main function prints 10 while the one in func prints 1. Is it possible to do so in C language?
EDIT: I know other alternatives like wrapping the array into a struct etc. Actually, I was trying to solve a problem given on TopCoders site and the requirement of one problem is that I have to write a function(requirement given below). Now I am confused that how I am going to calculate the size of the int[] donations array inside int maxDonations(int[] donations) function.
Definition
Class: BadNeighbors
Method: maxDonations
Parameters: int[]
Returns: int
Method signature: int maxDonations(int[] donations)
(be sure your method is public)
If you want, I can post the entire question.
A cheap way would be to wrap the array into a struct and pass that (or a pointer to the struct).
However, I would recommend passing an additional size_t argument that specifies the size of the array. This would make your function more flexible.
In C you cannot pass an array as a parameter to a function directly. You can pass a structure, a pointer or some other numeric value, but not an array.
Based on the constraints in your question, this question is impossible to answer.
In C, sizeof is an operator, rather than a function: you correctly mention this in your question. However, C operators are evaluated at compile time, rather than runtime, which means that you cannot use sizeof in a function in the way you want to - at compile time the compiler cannot tell how func() is going to be called.
Looking at the problem as set, I am assuming it is this one:
http://www.cs.duke.edu/csed/algoprobs/neighbors.html
The required method signature on that page is:
public int maxDonations(int[] donations)
although for some reason, you've omitted the public keyword in your question. This keyword indicates that the language in question is not C, and this example solution looks very much as if it is written in Java, in which language this is a non-problem, arrays have a length member.
I'd suggest you clarify the requirements for the question from your teacher/website/whatever to check what is really expected.