19-11-2010, 10:15 AM
The C Standard says (C90, Section 6.5.2.2) that each enumerated type is compatible with an integer type but the choice of integer type is implementation-defined. Many implementations, including those for some popular embedded processors, choose the smallest type that can contain the range of values of the enumeration constants. This type may be signed or unsigned. So, an enum object may be an int but it may be some other integer type.
The C Standard also says (C90, Sections 6.1.3.3 and 6.5.2.2) that the enumeration constants have type int, regardless of the integer type that is used to represent their parent enumerated type. Section 6.5.2.2 also constrains enumeration constants to have a value that is representable as an int.
The underlying type of an enumeration constant is determined from the table in MISRA C:2004 Guidelines Section 6.10.4. But, note that the Guidelines say, also in Section 6.10.4, that if the actual type of the expression is (signed) int ,then the underlying type is the smallest signed integer type capable of representing the value. Since all enumeration constants have type int, the underlying type of all enumeration constants is signed.
The code example:
violates Rule 10.1 because the right operand of = has underlying type signed char and this is implicitly converted to an unsigned 16-bit type. A type cast will be needed to avoid this violation. However, the code also violates Rule 12.7 because the bitwise OR operator is applied to operands with a signed underlying type. A better solution might therefore be to cast the enumeration constants to an unsigned type, e.g.
It might be worth using macros to perform the casts and thereby provide unsigned versions of the enumeration constants, e.g.
To recap the answers to the concluding questions:
No, enum constants are always signed.
That would depend on the nature of the expressions but code such as:
will not violate any arithmetic type rules.
The C Standard also says (C90, Sections 6.1.3.3 and 6.5.2.2) that the enumeration constants have type int, regardless of the integer type that is used to represent their parent enumerated type. Section 6.5.2.2 also constrains enumeration constants to have a value that is representable as an int.
The underlying type of an enumeration constant is determined from the table in MISRA C:2004 Guidelines Section 6.10.4. But, note that the Guidelines say, also in Section 6.10.4, that if the actual type of the expression is (signed) int ,then the underlying type is the smallest signed integer type capable of representing the value. Since all enumeration constants have type int, the underlying type of all enumeration constants is signed.
The code example:
Code:
s.x = (FIELD1 | FIELD2);
violates Rule 10.1 because the right operand of = has underlying type signed char and this is implicitly converted to an unsigned 16-bit type. A type cast will be needed to avoid this violation. However, the code also violates Rule 12.7 because the bitwise OR operator is applied to operands with a signed underlying type. A better solution might therefore be to cast the enumeration constants to an unsigned type, e.g.
Code:
s.x = ((my_uint16_t)FIELD1 | (my_uint16_t)FIELD2);
It might be worth using macros to perform the casts and thereby provide unsigned versions of the enumeration constants, e.g.
Code:
#define FIELD1_U ((my_uint16_t)(FIELD1))
To recap the answers to the concluding questions:
Quote:To conclude, I would like to know if enum constants should inherit the signedness from the initializer expressions
No, enum constants are always signed.
Quote:and, if so, should the tools issue a MISRA-C error for expressions involving enum objects and enum constants?
That would depend on the nature of the expressions but code such as:
Code:
enum { A, B } e;
...
e = A;
if (A < B) { ... }
will not violate any arithmetic type rules.
Posted by and on behalf of the MISRA C Working Group