essential type of constant expression - Printable Version +- MISRA Discussion Forums (https://forum.misra.org.uk) +-- Forum: MISRA C (https://forum.misra.org.uk/forumdisplay.php?fid=4) +--- Forum: MISRA C:2012 and MISRA C:2023 guidelines (https://forum.misra.org.uk/forumdisplay.php?fid=21) +---- Forum: 8.10 The essential type model (https://forum.misra.org.uk/forumdisplay.php?fid=165) +---- Thread: essential type of constant expression (/showthread.php?tid=1369) |
essential type of constant expression - sowiso - 26-09-2017 In Appendix D.1 the following limitation for the paragraphs D.n: Quote: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. What exactly is meant by expression? For example if I have the following code: Code: 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: Quote:1. If the operands are both essentially signed thenSince one is essentially signed while the other is essentially unsigned the result is the standard type which is unsigned int. 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. => 180Lu 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. Quote:"2. Else if the operands are both essentially unsigned"This gives the result as 60u which has the UTLR of unsigned char. 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? Re: essential type of constant expression - misra-c - 30-01-2018 Code: uint_8 foo = (((uint_8)(900000Lu / 5000Lu)) - ((uint_8)(600000Lu / 5000Lu))) - 1u; 1. 900000Lu ( and other Lu literals) The literal has a C standard type of "unsigned long", which has a rank greater than the rank of "int". Therefore the essential type is the same as the standard type which is "unsigned long". 2. 900000Lu / 5000Lu The "/" operation is between 2 literals with a C type and ET of "unsigned long". The resultant C type is "unsigned long", which has a rank greater than the rank of "int". Therefore the essential type is the same as the standard type which is "unsigned long". 3. (uint_8)(900000Lu / 5000Lu) This casts a C "unsigned long" type to "unsigned char". Casts are not listed in Appendix D.7 and so the essential type will be that of the cast. i.e "unsigned char". 4. (uint_8)(600000Lu / 5000Lu) For the same reasons as 1 - 3 the essential type is "unsigned char" 5. (((uint_8)(900000Lu / 5000Lu)) - ((uint_8)(600000Lu / 5000Lu))) The "-" operation is between two C types of "unsigned char". C's unary promotion rule promotes each operand to "signed int" and therefore the C resultant type of the expression is "signed int". As the C type of the expression is "signed int", the essential type is determined by the value of the expression. The value of the expression is 60 and hence the UTLR and essential type is "unsigned char". 6. 1u The literal has a C type of "unsigned int" and an essential type of "unsigned char". 7. (((uint_8)(900000Lu / 5000Lu)) - ((uint_8)(600000Lu / 5000Lu))) - 1u The "-" operation is between the C types of "signed int" and "unsigned int", and the essential types of "unsigned char" and "unsigned char". C's promotion rules converts the LH operand to "unsigned int", so the C resultant type of the expression is "unsigned int". As the C type of the expression is "unsigned int", the essential type is determined by the value of the expression. The value of the expression is 59 and hence the UTLR and essential type is "unsigned char". |