Hello everyone,
I've been trying to make a struct and compiler gives me expected identifier error. Can anyone tell me where is my fault?
struct State { unsigned long Out1; unsigned long out2; unsigned long Time; unsigned long Next[8];}; typedef const struct State STyp; #define gow 0; #define waitw 1; #define gos 2; #define waits 3; #define gop 4; #define fastp 5; STyp FSM[6]={ {0x0c,0x02,500,{gow,gow,wait,waitw,waitw,wait,wait,wait }},//error: expected'}' error: expected identifier or '(' {0x14,0x02,200,{gos,gos,gos,gos,gop,gop,gos,gos}}, {0x21,0x02,500,{gos,waits,gos,waits,waits,wait,waits,waits}}, {0x22,0x02,200,{gow,gow,gow,gow,gop,gow,gop,gop}}, {0x24,0x08,500,{gop,fastp,fastp,fastp,gop,fastp,fastp,fastp}}, {0x24,0x02,200,{gow,gow,gos,gow,gow,gow,gos,gow}}}; //error: extraneous closing brance ('}')
Thank you,
Just some notes about the above code:
#define gow 0; #define waitw 1; #define gos 2; #define waits 3; #define gop 4; #define fastp 5;
It's common practice to use upper-case for #define symbol names, to make sure anyone reading a different part of the code will instantly be aware that the symbol is "strange" and that it may be important to look up exactly what it is expected to expand into - such as in this case where the symbol expansion added an additional ';' character.
Next thing - it's common practice to use symbol names that a reader will understand. It isn't obvious to a reader what the difference is between "waitw" and "waits".
Third - if the symbol names can't give enough information, it's common to consider comments. But comments are normally needed to answer "why" while the symbol names are expected to answer "what".
And fourth - #define isn't really the way to label a sequence of integer values. The C language did get the enum construct for that situation. Being part of the C base language instead of part of the preprocessor, it doesn't just rely on a glorious text replacement mechanism but brings in type information and can give the compiler a way of detecting unhandled values.
typedef enum { Sleep, Swim, Walk, Run, Jump } Actions; ... switch (action) { case Sleep: waste_time(); break; case Swim: take_a_swim(); break; case Walk: stroll_around(); break; case Run: stroll_on_turbo_speed(); break; }
In the above code, a nice compiler can produce a warning, wondering why the switch statement didn't handle the Jump action. That would not be possible with code relying on #define.
In the above code, a nice compiler can produce a warning, wondering why the switch statement didn't handle the Jump action.
Interesting. I've never used one compiler which reports (or even detects) that one.
Most compilers seem not to report such things. For this reason, I regularily use PCLint on our code. For example:
/*! @brief Check if heater is running normally and temperature is good * * Considers device parameter settings * * @param[in] - * @param[out] - * @return bRunningAndGood */ bool HEATERSTATE_IsHeaterRunningAndTemperatureGood(void) { bool bRunningAndGood = FALSE; switch (m_tHeaterState.eState) { case HEATER_STATE_OFF: case HEATER_STATE_WARMUP: case HEATER_STATE_SETTLING: break; case HEATER_STATE_ON: bRunningAndGood = TRUE; break; case HEATER_STATE_ON_BUT_OUT_OF_TEMP: case HEATER_STATE_OVERTEMP_ERROR: if (g_tDeviceConfig.bDisableTemperatureErrors) { bRunningAndGood = TRUE; } break; //default: //break; } return bRunningAndGood; }
This gives some messages like
heaterstate.c(274,2): Info 787: enum constant 'HEATER_STATE::HEATER_STATE_ADC_REF_SENSOR_ERROR' not used within switch
When default is inserted, this changes to
heaterstate.c(274,2): Info 788: enum constant 'HEATER_STATE::HEATER_STATE_ADC_REF_SENSOR_ERROR' not used within defaulted switch
Martin
"Interesting. I've never used one compiler which reports (or even detects) that one."
gcc -Wall (or -Wswitch) can give:
warn_enum.c:10:12: warning: enumeration value âState3â not handled in switch [-Wswitch]
gcc does not emit any warnings if the switch has a default: case.
The warning is emitted if an enum-typed variable is used. So
int eval_state(State state) { switch (state) { case State1: return 1; case State2: return 2; } return -1; }
does give a warning, while the use of an int variable like:
int eval_state(int state) { switch (state) { case State1: return 1; case State2: return 2; } return -1; }
does not give a warning.
It doesn't hurt to take advantage of whatever "lint" capabilities a compiler may have.
Thanks for the info. For various reasons, I've never got round to using gcc much.