1

I am trying to define a generic macro in c which does a state transition in a state machine and "logs" some data on the state transition (reason of the transition and the number of transitions done).

As this approach shall be used in multiple state machines i want to use a generic macro like:

#define STATE_TRANSITION(state_variable, new_state, reason)  /
    state_variable.state = new_state;   /          /* new_state is an enum value */
    state_variable.transition_reason = reason; /   /* reason is an enum value */
    state_variable.state_transition_counter++;     /* the counter may overflow */

To make this possible i am thinking of a state type like this

struct specific_state {
    enum POSSIBLE_STATES state;
    enum STATE_TRANSITION_REASONS transition_reason;
    uint8 state_transition_counter;
}

which can be used for a specific state machine.

To make sure that every state uses the same structure (to make the macro work) i try to use some parent type for a state. My problem is that enum POSSIBLE_STATES and enum STATE_TRANSITION_REASONS can vary for the different statemachines. But the only generic member in my struct would be state_transition_counter :)

My question is now:

Is there a possibility to define a type in c which represents a base "class" like:

struct debuggable_state {
    enum state;
    enum transition_reason;
    uint8 state_transition_counter;
}

which can be subclassed afterwards (to apply the specific enum types)?

Perhaps i will replace the macro by an inline function to make it type safe, but i am still not sure if my approach is possible at all.

maggie
  • 3,935
  • 3
  • 27
  • 31
  • 2
    Unrelated to your problem, but besides that the line continuation characters is wrong (it's the backslash \\), you should be careful with multi-statement macros like yours. What if you put it in a `if` statement, and forget the curly-braces around it? – Some programmer dude Nov 05 '14 at 15:18
  • Not entirely sure what you're asking, but have you tried unions? – simonzack Nov 05 '14 at 15:20
  • It's best to always put complex macros in a do while(0) – Jonathon Reinhart Nov 05 '14 at 15:20
  • 1
    Related to your problem, you do know that *any* enumeration value can be implicitly converted to `int`? – Some programmer dude Nov 05 '14 at 15:20
  • To solve the x not the y, http://stackoverflow.com/questions/1371460/state-machines-tutorials – IdeaHat Nov 05 '14 at 15:21
  • 1
    @MadScienceDreams Only the simplest questions and the most obvious ones can be labelled "x y" problems. This isn't one of them. – simonzack Nov 05 '14 at 15:31
  • @simonzack I didn't say it was, I was just suggesting an alternative for the x that would avoid the issue. – IdeaHat Nov 05 '14 at 16:12
  • @Joachim and Jonathon: Thanks for the comments, you are right. I am just using pseudo code here. – maggie Nov 05 '14 at 16:17
  • @Joachim: I think the compiler will throw a warning because of the type mismatch? I know the an enum is just an int (depending on the compiler/platform). – maggie Nov 05 '14 at 16:21
  • @MadScienceDreams: I am dealing with embedded legacy code and i want to ease debugging at the moment. Perhaps i will rewrite the state machines in a seconds step. At the moment this is not my target. – maggie Nov 05 '14 at 16:22
  • @JoachimPileborg: Concerning your first comment: I am not sure if i understand that right, but then i would repeat my self a lot. And i want to avoid that. – maggie Nov 05 '14 at 16:28
  • why do you want to use a base class? Let's say you define two structs state_foo and state_bar, your macro would work without base class, right? – Étienne Nov 05 '14 at 16:34
  • Yes, you are right. But with a base class i cannot forget to define a member. Of course this is more a question regarding c language than a question of realization. – maggie Nov 05 '14 at 16:38
  • That does not make sense, your macro will not compile if you forget to define a member. A base class is not possible here, since you want to use a different enum for each struct. – Étienne Nov 05 '14 at 18:05
  • You are right! And this answers my question. Thanks! – maggie Nov 05 '14 at 20:17
  • the struct specific_state should not be trying to define enum(s). Which it is currently doing. Rather make the first two entries 'int' , which will translate correctly for any enum. and wrap the statements of the macro in do { ... } while(0); so they will be treated as a single code block. – user3629249 Nov 05 '14 at 23:05
  • Glad it helped :) By the way, when using comments on stackoverflow, you should use (for example to address me) "@Étienne", then I would get a notification that you answered. (You get notified that I commented because you wrote the question). – Étienne Nov 05 '14 at 23:05
  • @user3629249: If i use ints the macro could be fed with any int value, also values which are not part of the state's enum (POSSIBLE_STATES). I would like to allow only values of the enum of the state. – maggie Nov 06 '14 at 07:06
  • 1
    @maggie Don't forget enums are not type-safe in C (unlike in C++), you can assign any value to an enum, the compiler will not complain. You will have to check manually that a valid value is being assigned if that's what you want. – Étienne Nov 06 '14 at 09:55
  • @Étienne: Oh, i was not aware of this! Thanks for the hint. – maggie Nov 06 '14 at 09:57

1 Answers1

0

You could use int instead of the enums in the generic struct, the enums are represented as int anyway..

Giordano
  • 311
  • 2
  • 5