I am trying to create a FSM in C. I am using a variation of the STATE pattern for C that is explained here. The problem is that I am in the embedded world and they make me comply with some safety-critical rules. One of these rules says that I can't use non-const pointers to functions, so I have created my fsm like this:
typedef struct tFsm* tFsmPtr;
/* PLEASE NOTE: This is a non const struct with its member
* being a const pointer to a function. */
typedef struct
{
void (*const raise)(tFsmPtr);
} tEvent;
struct tFsm
{
/* Because the tEvent type is non const,
* I can modify these fields */
tEvent start;
tEvent started;
tEvent stop;
tEvent stopped;
};
static void DefaultInvalidEventCallback(tFsmPtr fsm)
{
/* Raise an error */
}
static struct tFsm m_fsm = {
.start = { .raise = &DefaultInvalidEventCallback },
.started = { .raise = &DefaultInvalidEventCallback },
.stop = { .raise = &DefaultInvalidEventCallback },
.stopped = { .raise = &DefaultInvalidEventCallback }
};
No errors so far. The problem is that when I try to modify any field of the struct tFsm
, it complains. For example this code:
void ResetFsm( tFsmPtr fsm )
{
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
}
The compiler complains saying that:
prog.c: In function 'ResetFsm':
prog.c:32:22: error: assignment of read-only member 'start'
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:33:22: error: assignment of read-only member 'started'
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:34:22: error: assignment of read-only member 'stop'
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:35:22: error: assignment of read-only member 'stopped'
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
My questions are: Could you please tell me why the compiler complains here? Is there a way of using const pointers to functions here?
Thanks in adavance.
Member raise
of struct tEvent
, is defined with const:
void (*const raise)(tFsmPtr);
This means that only initialization of the entire struct is possible:
tEvent s = { DefaultInvalidEventCallback };
but assignment of the entire struct is not:
tEvent a;
a = s;
This of course holds true for any struct which has the struct tEvent
as its member, for example: struct tFsm
, as shown in your example