MISRA Discussion Forums

Full Version: int vs long when sizes are identical and issue with int32_t (from rule 6.3) in rule 10.1 example
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Rule 10.1 contains the following example:
Code:
s32a = s16a + (int32_t)20000; /* compliant */
Rule 6.3 suggests this definition of int32_t:
Code:
typedef signed int int32_t;
The addition expression is a complex expression per 6.10.5.
The underlying type of s16a is int16_t.
The underlying type of (int32_t)20000 is int16_t because this is an integral constant expression and the "actual type" is int per 6.10.4:
Quote:If the actual type of the expression is (signed) int, the underlying type is defined to be the smallest signed integer type which is capable of representing its value.

The underlying type of the sum is then int16_t (not int32_t as the example seems to assume).
int16_t is being assigned to int32_t which requires a conversion to change the underlying type, but this is a violation of rule 10.1 because the sum is a complex expression. Thus the example appears not to be compliant.

Is this example incorrect when int32_t is int?
It appears that the behavior would be different if int32_t were long because the integral constant expression rule would not apply, is this intentional? How should this potential difference in the definition be handled?
If int and long are the same size, does conversion between int and long violate rule 10.1 because it only allows conversions to wider types and not to types of the same size?
Thank you for raising these issues which have shown an error in the MISRA-C:2004 document. The example line should have read
Code:
s32a = s16a + (int32_t)20000; /* not compliant */

1st Question:
Your comments are correct . The underlying type for (int32_t)20000 is int16_t for the reasons described above and therefore rule 10.1 is violated as there is an implicit conversion to a different underlying type of a complex expression.
The example should have a "not compliant" comment. The "underlying type" model was re-visited in MISRA-C:2012 where such issues are clarified.

2nd Question:
Now consider an example
Code:
typedef signed long int64_t;
   int64_t s64;
   s64 = s32 + (int64_t)20000;  /* compliant */
You are correct in saying that in this case the underlying type of "(int64_t)2000" is int64_t. The underlying type of a integer constant expression is only different if the standard C type of the expression is unsigned int or signed int. In this case the standard C type for "(int64_t)2000" is "signed long" and so the underlying type is also "signed long". The result of the "+" operation is therefore "signed long" and the whole expression is compliant with rule 10.1.

3rd Question:
Now consider an example whether int and long have the same size.
Code:
typedef signed int INT_32;
   typedef signed long LONG_32;
   INT_32  si_32;
   si_32 = si_32 + (LONG_32)20000;  /* compliant */
The standard C type for the "+" operation is "signed long" and hence the underlying type is "signed long".
The conversion on assignment is between "signed long" and "signed int", which are both 32-bits in this part of the question. The intention of rule 10.1 is that conversions between "underlying types" of the same size are permitted, reqardless of the standard C type used.
Code:
LONG_32 sl32;
si_32 = sl_32;  /*  compliant */