What is the essential type of "~(uint16_t)0x30" ?
Going by Appendix D "Bitwise complement":
* The operand is essentially unsigned
* The operand is an integer constant expression
* The result of "~(uint16_t)0x30" is 49 of standard type int (assuming int is 32 bits and twos complement).
* The UTLR of 49 is illdefined.
Option 1: If the resulting constant is negative, convert it to the unsigned type corresponding to the expression's standard type, then use the UTLR of that converted value. This would result in "~(uint16_t)0x30" having essential type "unsigned int" (same as without the cast to uint16_t).
Option 2: If the resulting constant is negative, treat the expression as if it was nonconstant, using the essential type of the operand instead. This would result in "~(uint16_t)0x30" having essential type "uint16_t" (same as if 0x30 wasn't a compiletime constant).
Option 3: If the resulting constant is negative, use the standard type for the essential type. This would result in "~(uint16_t)0x30" having essential type "signed int".
This also affects other constant expressions producing negative values after integral promotion, e.g. "(uint16_t)300u  (uint16_t)301u".
Essential type of ~(uint16_t)0x30
Moderators: misrac, david ward

 Posts: 15
 Joined: Wed May 14, 2014 1:02 pm
 Company: Axivion GmbH

 Posts: 569
 Joined: Thu Jan 05, 2006 1:11 pm
Re: Essential type of ~(uint16_t)0x30
This discussion assumes that "uint16_t" is a 16bit unsigned short, and that "uint32_t" is a 32bit 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:
Therefore the result is of the ~ operator has an essential type which is unsigned. The value of the result occupies 32bits 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:
The operand is essentially unsigned and the operand is an integer constant expression, so option 1.1 is selected.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.
Therefore the result is of the ~ operator has an essential type which is unsigned. The value of the result occupies 32bits 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: Select all
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
"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 32bits and hence the UTLR is "unsigned int".

Posted by and on behalf of
the MISRA C Working Group
Posted by and on behalf of
the MISRA C Working Group