It depends on what integer type is selected by the compiler to be compatible with the enumeration type. The compiler can select an unsigned integer type.
In this statement
printf("now a is %d\n", a);
you are using the conversion specifier %d
designed for signed integer types though the enumeration can be compatible with an unsigned integer type and if you will use the conversion specifier %u
you will get another result.
If for example you will declare an enumeration constant as having a negative value then the compiler will select a signed integer type as compatible with the enumeration.
Here are two demonstrative programs that show the difference
#include <stdio.h>
int main( void )
{
enum Direction {N,W,S,E};
enum Direction a = N;
--a;
printf( "a < 0 is %d\n", a < 0 );
}
The output of this program is
a < 0 is 0
The compiler selected an unsigned integer type as the compatible integer type.
#include <stdio.h>
int main( void )
{
enum Direction {N = -1, W,S,E};
enum Direction a = W; // W is equal to 0
--a;
printf( "a < 0 is %d\n", a < 0 );
}
The output of this program is
a < 0 is 1
because the compiler selected a signed integer type as the compatible integer type.
Form the C Standard (6.7.2.2 Enumeration specifiers)
4 Each enumerated type shall be compatible with char, a signed integer
type, or an unsigned integer type. The choice of type is
implementation-defined,128) but shall be capable of representing the
values of all the members of the enumeration. T
That is there is a difference between an enumeration type and an enumeration constant. Enumeration constants always have the type int
. But enumeration types are compatible with integer types (signed or unsigned) selected by the compiler.
Compare the two calls of printf
in this demonstration program.
#include <stdio.h>
int main( void )
{
enum Direction {N,W,S,E};
enum Direction a = N;
printf( "a - 1 < 0 is %d\n", a - 1 < 0 );
printf( "N - 1 < 0 is %d\n", N - 1 < 0 );
}
where the program output is
a - 1 < 0 is 0
N - 1 < 0 is 1