Verify that all set values of an enum are distinct - c

I just recently found out that when setting values of variables of an enum, several variables can have the same value. For example, the following code is perfectly correct:
enum my_enum
{
A = 3,
B = 4,
C = 3,
D = 5
};
However, in my framework, I have to set manualy each variable, since it is used to communicate error codes to other systems. I cannot change the value of an error code without asking for the other teams to modify it as well.
I regrouped all error codes into an enumeration to be sure we do not reuse the same error code for different reasons (which was the case before). But now, nothing stops anyone to reuse the same value for different errors.
Is there a way I can make the compiler return an error if I assign the same value to different names in my enum?
I can compile with either gcc or clang.

A switch statement cannot have two cases with the same value. So you can have a switch somewhere. Make it with no default: case and gcc will warn you that a member of the enum is not handled in the switch statement if you add a new value. If two values of the enum are the same, compilation will fail.
Some examples:
typedef enum {
ERR_NONE = 0,
ERR_SAME = 0
} err_t;
volatile err_t e = ERR_NONE;
int main( int argc, char* argv[] )
{
switch( e )
{
case ERR_NONE:
break;
case ERR_SAME:
break;
}
return 0;
}
with gcc -Wall switch.c gives:
switch.c: In function 'main':
switch.c:16:9: error: duplicate case value
case ERR_SAME:
^
switch.c:13:9: error: previously used here
case ERR_NONE:
^
and...
typedef enum {
ERR_NONE = 0,
ERR_NEXT,
ERR_MISSING,
} err_t;
volatile err_t e = ERR_NONE;
int main( int argc, char* argv[] )
{
switch( e )
{
case ERR_NONE:
break;
case ERR_NEXT:
break;
}
return 0;
}
with gcc -Wall switch-missing.c gives:
switch-missing.c: In function 'main':
switch-missing.c:12:5: warning: enumeration value 'ERR_MISSING' not handled in switch [-Wswitch]
switch( e )
^

Related

C switch statement and enum explicit cast

Saw a lot of similar questions but none answer my question here:
Suppose I have an enum Property:
enum
{
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
When I try to use it in a switch statement like this:
// file test.c
enum
{
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
int main(void)
{
int a = 0;
switch ((Property) a)
{
case PROP_A:
break;
case PROP_B:
break;
default:
break;
};
return 0;
}
The compiler throws this error:
test.c: In function ‘main’:
test.c:11:20: error: expected ‘)’ before ‘a’
11 | switch ((Property) a)
| ~ ^~
| )
What is wrong with this code? For reference, in the GObject documentation they have this snippet:
typedef enum
{
PROP_FILENAME = 1,
PROP_ZOOM_LEVEL,
N_PROPERTIES
} ViewerFileProperty;
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
static void
viewer_file_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ViewerFile *self = VIEWER_FILE (object);
switch ((ViewerFileProperty) property_id)
{
case PROP_FILENAME:
g_free (self->filename);
self->filename = g_value_dup_string (value);
g_print ("filename: %s\n", self->filename);
break;
case PROP_ZOOM_LEVEL:
self->zoom_level = g_value_get_uint (value);
g_print ("zoom level: %u\n", self->zoom_level);
break;
default:
/* We don't have any other property... */
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
Which is essentially the same thing. Therefore it must be possible. What's wrong with my version?
In this declaration
enum
{
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
you declared an object Property of an unnamed enumeration type.
So in the switch statement
switch ((Property) a)
you are using a syntactically incorrect expressions with two objects Property and a.
It seems you mean
typedef enum
{
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
Pay attention that you may just write
switch ( a )
In C enumerators have the type int. That is these enumerators PROP_A, PROP_B, N_PROPERTIES all have the type int. So the casting that you tried to apply (if the enumeration would be declared correctly) is redundant.
Suppose I have an enum Property:
enum
{
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
Your code does not define Property as an enum type. It declares it as a variable whose type is an untagged enum type. Typecast operators must be constructed from types, not variables, so (Property) a is invalid.
That cast is also unnecessary. One way to solve the problem would be simply to drop it:
switch (a) {
case PROP_A:
break;
case PROP_B:
break;
default:
break;
}
Alternatively, if you mean to define Property as a type alias, then that is the function of typedef:
typedef enum {
PROP_A = 1,
PROP_B,
N_PROPERTIES
} Property;
Personally, however, I am not a fan of typedef. It has a few good uses, but it tends to be applied far beyond those. If I wanted to declare an enum type that I could reference apart from its declaration, then I would include a tag:
enum property {
PROP_A = 1,
PROP_B,
N_PROPERTIES
};
int main(void) {
int a = 0;
switch ((enum property) a) {
case PROP_A:
break;
case PROP_B:
break;
default:
break;
}
return 0;
}
(The cast is included for demonstrative purposes -- it's still unnecessary.)
You need to add typedef before enum to identify Property as a type. In the other example you provided for comparison, typedef is used.

Why does gcc throw an implicit-fallthrough warning?

Given the code:
#include <stdlib.h>
enum one {
A, B
};
enum two {
AA
};
int main(int argc, char *argv[])
{
enum one one = atoi(argv[1]);
enum two two = atoi(argv[2]);
if ((one != A && one != B) || two != AA)
return 1;
switch (one) {
case A:
switch (two) {
case AA:
return 2;
}
case B:
return 3;
}
return 0;
}
When I compile it using using gcc -Wimplicit-fallthrough test_fallthrough.c I get the following warning
test_fallthrough.c: In function 'main':
test_fallthrough.c:21:3: warning: this statement may fall through [-Wimplicit-fallthrough=]
21 | switch (two) {
| ^~~~~~
test_fallthrough.c:25:2: note: here
25 | case B:
| ^~~~
What is it trying to warn against and what can I do so that it does not warn (I would prefer to avoid adding comments such as /* Falls through. */)
Why does gcc throw an implicit-fallthrough warning?
Well, because it may fallthrough.
What is it trying to warn against
A fallthrough from case A into case B when two != AA.
what can I do so that it does not warn
On gcc lower then 7 use a comment, ie. one of the markers that disable the warning:
/* falls through */
On gcc above 7 you could use a attribute:
__attribute__((__fallthrough__));
On gcc above 10 you could use the attribute from C2x:
[[fallthrough]];
--
Note that if (one != A || one != B || two != AA) is not really checking anything, as one != A || one != B will always be true. I guess you meant to do like if ((one != A && one != B) || two != AA). Still the -Wimplicit-falthrough= warning is not taking that if into account anyway.
You're missing a break in the first switch statement, it may fallthrough to the sencond case, it can execute case A and afterwards Case B, hence the warning.
//...
switch (one)
{
case A:
switch (two)
{
case AA:
return 2;
}
break; //breaking case A removes the warning.
case B:
return 3;
}
//...
Side note:
Using argc to check if argv[1] and argv[2] are present is always a good idea.
Usually, compiler checks for a break statement after every case body, so that it can ensure the program flow (fallthrough) is not a mistake.
In your case, case A body does not have a break, letting the execution to continue for case B also, when the switch statement matches that of case A.
switch (one) {
case A:
switch (two) {
case AA:
return 2;
}
// <------ no break here, flow will continue, or fall-through to next case body
case B:
return 3;
}
return 0;
}

Parse to integer with argp.h

I would like to be able to receive program arguments and options in my C program. The options should be treated as floats or ints. For some reason, I couldn't find good articles, tutorials, docs about argp.h. I started my implementation with the examples on the GNU Libc Manual, though unfortunately, it didn't get me to the solution.
Here is how I tried to solve the problem (example can be compiled, included every necessary line):
#include <stdlib.h>
#include <argp.h>
static char doc[] = "Doc";
static char args_doc[] = "ARG1";
static struct argp_option options[] = {
{"bool", 'b', 0, 0, "Simple boolean flag, works as I expected."},
{"int", 'i', 0, 0, "Would like to be able to parse options as --int=4 or -i 4."}, // but I can't
{0}
};
struct arguments {char *args[1]; int xbool, xint;};
static error_t
parse_opt (int key, char *arg, struct argp_state *state) {
struct arguments *arguments = state->input;
printf("key = %c, arg = %s\n", key, arg); // My attempt to understand the problem
//if (arg == NULL) return 0; // Prevents segfaults, in order to see how the args and keys change
switch (key) {
case 'b': arguments->xbool = 1; break;
case 'i': arguments->xint = (int) strtol(arg, NULL, 10); break;
case ARGP_KEY_ARG: if (state->arg_num >= 1) {argp_usage(state);} arguments->args[state->arg_num] = arg; break;
case ARGP_KEY_END: if (state->arg_num < 1) {argp_usage(state);} break;
default: return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = { options, parse_opt, args_doc, doc };
int main (int argc, char **argv) {
struct arguments arguments;
arguments.xbool = 0;
arguments.xint = 0;
argp_parse (&argp, argc, argv, 0, 0, &arguments);
printf("ARG1 = %s\nbool option = %s\nparsed int option = %d",
arguments.args[0], arguments.xbool ? "true" : "false", arguments.xint);
exit (0);
}
The simple boolean flag works, as expected, so ./myprogram.out myarg --bool and ./myprogram.out myarg -b changes the flag's value.
However, I can't seem to find a way to parse the arguments as integers or floating point numbers.
This it the output I get for ./a.out -b --int=2 myarg:
key = , arg = (null)
key = b, arg = (null)
./a.out: option '--int' doesn't allow an argument
Try `a.out --help' or `a.out --usage' for more information.
and for ./a.out -b --int 2 myarg I get a segmentation fault, as I try to parse a NULL: key = i, arg = (null). I added a NULL check, and this way I could see, that the option I would like to parse comes with a , key (expected to come with i).
key = i, arg = (null)
key = , arg = 2
I thought about using a library because the program needs to handle various float and int options, falling back to default values, and I've seen often that it's not recommended to roll your own argument and options parser. Based on the examples, argp.h looked promising, however I couldn't get it to work yet.
ps. I know that parsing directly to ints and floats are not part of argp, this is why I was (naively, it seems) trying to add it to the structures and parse_opt function.
As it turned out, there was an error with options[]. The third, const char *arg parameter in the argp_option struct must be provided, if the option has argument associated with it [source: GNU C: Argp Option Vectors].
static struct argp_option options[] = {
{"bool", 'b', 0, 0, "Simple boolean flag, works as I expected."},
{"int", 'i', "Numbah", 0, "Now everything works as expected, I get the correct key-value (key-arg) pair in the parse_opt function"},
{0}
};

C programming lookup table

After some help as have some code which works but trying to fully understand a small section which uses a lookup table as part of a state machine. The state machine I understand and have been using for a tutorial I am writing found here http://coder-tronics.com/state-machine-tutorial-pt1
Instead of using more switch case statements inside the UponExit, UponEnter and ActionWhileInState, someone suggested using this method which I like but don't fully understand.
Now the part I am unsure about is these lines to do with the typedef and lookup table
typedef void (* const voidFunc)(void);
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
I looked up typedef and lookup tables and have a basic understanding, but was hoping someone could give a brief walk through of how this works in this case?
The full part of code this relates to is below for completeness.
enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
enum events { E_OFF, E_ON, E_START, E_MAX};
typedef void (* const voidFunc)(void);
void hEnter_OFF(void); void hEnter_ON(void); void hEnter_PROCESS(void);
void hInState_OFF(void); void hInState_ON(void); void hInState_PROCESS(void);
void hExit_OFF(void); void hExit_ON(void); void hExit_PROCESS(void);
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
enum states StateMachine(enum events event, enum states Current_State)
{
int Next_State = Current_State;
switch ( Current_State )
{
case S_OFF:
switch (event )
{
// A transition to the next state will occur here
case E_ON:
Next_State = S_ON;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
case S_ON:
switch (event )
{
// A transition to the next state will occur here
case E_OFF:
Next_State = S_OFF;
break;
case E_START:
Next_State = S_PROCESS;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
case S_PROCESS:
switch (event )
{
// A transition to the next state will occur here
case E_OFF:
Next_State = S_OFF;
break;
default: // Default case placed here to avoid Eclipse warnings as Eclipse expects
break; //to handle all enumerated values
}
break;
// The program should never arrive here
default:
break;
}
if (Next_State != Current_State)
{
// Function call for Upon Exit function, it can be omitted but allows extra functionality
UponExit[Current_State]();
// Function call for Upon Enter function, it can be omitted but allows extra functionality
if (Next_State != S_MAX) UponEnter[Next_State]();
}
else // I think ActionWhileInState should only be called when NOT doing a transition!
{
if ( event != E_MAX) ActionWhileInState[Current_State]();
}
return Next_State;
}
Thanks,
Ant
typedef void (* const voidFunc)(void);
is a typedef for a function pointer (for a pointer to a function expecting no parameters and not returning anything to be exact). So your arrays
voidFunc UponEnter[S_MAX] = {hEnter_OFF, hEnter_ON, hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] = {hExit_OFF, hExit_ON, hExit_PROCESS};
Each hold three different function pointers, one for each state. So a line like
UponExit[Current_State]();
calls the function the pointer UponExit[Current_State] points to which is hExit_OFF if Current_State is 0, hExit_ON if Current_State is 1 or hExit_PROCESS if Current_State is 2.
You could also write the line like that:
(*UponExit[Current_State])();
What looks more complicated but makes clear that UponExit[Current_State] is a function pointer that is "dereferenced" to a call to the function it points to.
Edit:
You have an enum for your states:
enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
Thus, S_OFF == 0, S_ON == 1, S_PROCESS == 2 and S_MAX == 3 (look here)

Constant integral expression required error

I am writing code for AVR ATmega32-A microcontroller. I am using switch case as shown below.
unsigned char Command;
unsigned int Param;
void runCom(void){
switch(Command){
case(NO_COM):
Command = 0;
break;
case(INF):
printf("\r\n\r\n");
printf("university\r\n");
printf("sweden\r\n");
printf("Ver. 1.0A\r\n");
Command = 0;
break;
case (DB):
Command = 0;
break;
case(CLEARM):
Command = 0;
break;
default:
Command = 0;
break;
}
}
the above code is working but now i want to add one more case in that switch like as shown below.
unsigned char Command, Command1;
unsigned int Param;
void runCom(void){
switch(Command){
case(NO_COM):
Command = 0;
break;
case(INF):
printf("\r\n\r\n");
printf("university\r\n");
printf("sweden\r\n");
printf("Ver. 1.0A\r\n");
Command = 0;
break;
case (DB):
Command = 0;
break;
case(ADC):
printf("ADC Value",ReadAd());
printf("Enter Amplification stage");
switch(Command1){
case(stage1):
PORTC=0x00;
DDRC=0xC0;
printf("ADC Value",ReadAd());
Command1 = 0;
break;
case(stage2):
PORTC=0x00;
DDRC=0x03;
printf("ADC Value",ReadAd());
Command1 = 0;
break;
}
Command = 0;
break;
case(MEM):
Command = 0;
break;
case(CLEARM):
Command = 0;
break;
default:
Command = 0;
break;
}
}
I am getting error like
undefind symbol 'ADC'
undefind symbol 'stage1'
undefind symbol 'stage2'
then i have declared like this
unsigned char Command, ADC, Command1, stage1, stage2;
unsigned int Param;
now i am getting error like
constant integral expression required at line case(ADC)
constant integral expression required at line case(stage1)
constant integral expression required at line case(stage2)
so please can any one suggest me how to overcome this error. I haven't declared WGP, WGF, INF any where but I am not getting "undefined symbol of WGF, WGP, INF. why this error occurring for ADC only. i have fallowed same switch case rules as i used before. any suggestions appreciated.
Thanks in advance.
The values in a case needs to be constants or literals.
If you look up e.g. WGP you will see that it's most likely a #define'd literal. Do the same for your new values.
The values you use in the cases of a switch statement must be compile-time constants. That is, they must have fixed values that are known to to the compiler at compile time.
There are four main ways to do this.
You can use a constant literal (a number).
case 42:
Note that using unnamed values ("magic numbers") isn't recommended because it doesn't document the code in any way, and makes the code fragile (what if you need to change the value to 43 in five different places and forget one?)
You can use a preprocessor constant.
#define COMMAND_CODE 42
...
case COMMAND_CODE:
That's better because if you need to changet the command code value to 43 you only have to change the #define (which should only occur once, in a header file).
You can use an enum.
typedef enum { COMMAND_ON=42, COMMAND_OFF=2, COMMAND RESET=77 } command_codes:
...
case COMMAND_ON:
In C++, if your compiler is reasonably modern, you can use a constant:
const int magic_number = 42;
case magic_number:
(Note that the switch value shown in a case statement does NOT need to have parentheses around it.)
From the code you have shown, it seems that you have defined Command, ADC, etc., as variables (rather than as constants). In this case the compiler can't know what value those variables will have at execution time when it compiles the code. The language specifies that case values must be known at compile time so that the compiler can generate fast code (faster then a whole series of if ... else if ... else if statements).

Resources