01-06-2020, 01:16 PM
This discussion assumes that "uint16_t" is a 16-bit unsigned short, and that "uint32_t" is a 32-bit unsigned int.
Taking the operators in turn.
(uint16_t)0x30 The result of the cast has an essential type of unsigned short and a value of 0x30
Appendix D on the ~ operator says:
The operand is essentially unsigned and the operand is an integer constant expression, so option 1.1 is selected.
Therefore the result is of the ~ operator has an essential type which is unsigned. The value of the result occupies 32-bits and so the essential type of the result is unsigned int.
You are correct in saying that small unsigned types are promoted to a "signed int" standard type, but have an "essentially unsigned" type. This is only an issue if the resultant value is treated as a signed value, otherwise the bit pattern is consistent with what a user would expect. Any attempt to use the value of the result in an essentially signed context will produce a violation of rule 10.1, 10.3 or 10.4.
Any use which might indicate a loss of bits is highlighted by a MISRA C:2012 warning.
The same argument follows for (uint16_t)300U - (uint16_t)301U. Appendix D on "-" paragraph 2.1 says
Taking the operators in turn.
(uint16_t)0x30 The result of the cast has an essential type of unsigned short and a value of 0x30
Appendix D on the ~ operator says:
Quote:1. If the operand is essentially unsigned then:
1.1 If the operand is an integer constant expression then the essential type
of the result is the UTLR of the result;
1.2 Else the essential type of the result is the essential type of the operand.
2. Else the essential type is the standard type.
The operand is essentially unsigned and the operand is an integer constant expression, so option 1.1 is selected.
Therefore the result is of the ~ operator has an essential type which is unsigned. The value of the result occupies 32-bits and so the essential type of the result is unsigned int.
You are correct in saying that small unsigned types are promoted to a "signed int" standard type, but have an "essentially unsigned" type. This is only an issue if the resultant value is treated as a signed value, otherwise the bit pattern is consistent with what a user would expect. Any attempt to use the value of the result in an essentially signed context will produce a violation of rule 10.1, 10.3 or 10.4.
Code:
uint16_t u16 = ~(uint16_t)0x30; // Rule 10.3 violation - uint16_t v uint32_t
uint32_t u32 = ~(uint16_t)0x30; // Compliant
int32_t s32 = ~(uint16_t)0x30; // Rule 10.3 violation - sint32_t v uint32_t
The same argument follows for (uint16_t)300U - (uint16_t)301U. Appendix D on "-" paragraph 2.1 says
Quote:"If the expression is an integer constant expression then the essential type of the result is the UTLR of the result;"
The result would have a value of -1 in the standard C operation which requires 32-bits and hence the UTLR is "unsigned int".
Posted by and on behalf of the MISRA C Working Group