You can tighten the structure at the cost of a carry an action size count. However it does allow you to use the same actions blocks for multiple states. That may often happen in that you just have things like confirm yes/no actions. I also changed your pointer definitions to const as you are clearly going to have static tables and it will save compiler type casting errors. I assume you are going to do this .. see the C11 initializers at code end which uses the standard _countof to autosize the arrays. on GCC it's ARRAY_SIZE() but I hate the name so always define it _countof same as MSVC because it reflects better what it is IMHO.
typedef bool (*returnTrueOrFalseFunctionPtr) (void);
typedef void (*actionFunctionPtr) (int);
struct myAction_s {
const actionFunctionPtr actionToPerformInThisState;
const uint32_t actionArgument;
};
struct myStruct_s {
returnTrueOrFalseFunctionPtr trueOrFalse;
const struct myStruct_s* whereToGoIfTrue;
const struct myStruct_s* whereToGoIfFalse;
const uint8_t maxActionsInThisState; // Count of the actions in this state
const struct myAction_s* actionsListInThisState; // The action block pointer
};
static void SomeYesFunc (int) {
}
static void SomeNoFunc(int) {
}
static void SomePerhapsFunc(int) {
}
static bool truefalseFunc(void) {
return true;
}
/* ACTION BLOCK DEFINITIONS */
const struct myAction_s yesNoBlock[2] = { &SomeYesFunc, 1 , &SomeNoFunc, 2 };
const struct myAction_s yesNoPerhapsBlock[3] = { &SomeYesFunc, 1 , &SomeNoFunc, 2, &SomePerhapsFunc, 3};
/* ACTION STATE DEFINITIONS */
const struct myStruct_s nullState = { 0, 0, 0, 0, 0};
const struct myStruct_s yesNoState = { &truefalseFunc, &nullState , &nullState, _countof(yesNoBlock), &yesNoBlock[0] };
const struct myStruct_s yesNoPerhapsState = { &truefalseFunc, &nullState , &nullState, _countof(yesNoPerhapsBlock), &yesNoPerhapsBlock[0] };
In vino veritas