What exactly is meant by expression?The essential type of an expression only differs from the standard C type (standard type) in expressions where the standard type is either signed or unsigned int.
For example if I have the following code:
Code: Select all
uint_8 foo = (((uint_8)(900000Lu / 5000Lu)) - ((uint_8)(600000Lu / 5000Lu))) - 1u;
In case I take the complete part from above as one single expression, for the code example the standard type of the complete expression would be evaluated to "(unsigned char - unsigned char) - unsigned int" which is promoted to "(signed int - signed int) - unsigned int" evaluated to "signed int - unsigned int" converted to "unsigned int - unsigned int" and finally results in "unsigned int".
Based on this result, which is unsigned int, the rules from D.7 needs to be applied.
However looking at the final expression "signed int - unsigned int" D.7 tells the following:
Since one is essentially signed while the other is essentially unsigned the result is the standard type which is unsigned int.1. If the operands are both essentially signed then
2. Else if the operands are both essentially unsigned then
3. Else the essential types are the standard type
The numerical value value in this case would be 59u which would have the UTLR as unsigned char.
But since case 3 applies the final type is still unsigned int and therefore an assignment to uint_8 type variable is prohibited because of Rule 10.3 "The value of an expression shall not be assigned to an object with a narrower essential type [...]".
Looking at this on a different way and evaluate each sub expression separately by use of the essential type model I come to a different result.
(((uint_8)(900000Lu / 5000Lu)) - ((uint_8)(600000Lu / 5000Lu))) -1u;
(900000Lu / 5000Lu): both types are unsigned long int and therefore also the result will be unsigned long int. D.7 does not apply because of D.1.
result of the cast to ((uint_8)(180Lu)) is the standard type as casts are not specified in D.7 giving the result at unsigned char 180u.
For (600000Lu / 5000Lu) it is the same result as unsigned long, cast afterwards to unsigned char 120u.
The next expression is then "unsigned char 180u - unsigned char 120u". The result of this is signed int and therefore D.7 applies.
This gives the result as 60u which has the UTLR of unsigned char."2. Else if the operands are both essentially unsigned"
"2.1 If the expression is an integer constant expression the essential type of the result is the UTLR of the result."
Now "unsinged char 60u - unsigned int 1u" will be promoted to "signed int - unsigned int" and converted to "unsinged int - unsigned int" returning an unsigned int. Therefore D.7 applies and the result will be 59u which has the UTLR of unsigned char.
Based on this an assignment to uint_8 type variable is allowed.
Now my question is, which of these two approaches is the right one?