MISRA Discussion Forums

Full Version: Underlying Types
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I was looking through the MISRA 2 Standard and was wondering what the underlying type of an expression is involving mixed types. For example suppose we are given the following variables:
int i1, i2, *ip;
unsigned char uc;
float f;
What is the underlying type of:
i1 | uc;
i2 ? i1 : uc;
&i1;
ip;
( i1 == i2 );
f;
Since the Standard goes into such detail regarding the concept of \"underlying type\", I feel this is an important issue which, to me, requires clarification.
** This response has been superseded - see below **

i1 and uc have a different signedness and hence the expressions i1 | uc and i2 ? i1 : uc are not compliant with Rule 10.1.a. However the resultant underlying type can be deduced by extending the usual arithmetic conversion rules, as described in section 6.2.1.5 of ISO 9899:1990, to underlying types. They are described more fully at the end of this response.

&i1 and ip both have an underlying type of int *.

( i1 == i2 ) has a type of int, which is understood to be its underlying type. This is mentioned in 6.10.2 in the section on balancing conversions. There was discussion, whilst the guidelines were being drawn up, as to whether there should be an underlying type of Boolean, but it was felt that other rules sufficiently restricted the use of Boolean expressions

f has an underlying type of float.

Usual arithmetic conversion rules and underlying types

The existing rules in section 6.2.1.5 of ISO 9899:1990 apply to underlying types except the statements \"otherwise, both operands have type int\" can be replaced by
1. If both operands have the same underlying type, no further conversion is needed.
2. Otherwise if both operands have the same signedness, the operand with smaller magnitude is converted to the type of the other operand.
3. Otherwise, if the type of the operand with underlying signed type can represent all of the values of the type of the operand with underlying unsigned type, then the operand with unsigned type is converted to the type of the operand with signed type.
4. Otherwise, both operands are converted to the underlying unsigned type corresponding to the type of the operand with the underlying signed type.
MISRA Reply Wrote:4. Otherwise, both operands are converted to the underlying unsigned type corresponding to the type of the operand with the underlying signed type.

Sounds "fine and dandy" to me, but what about an 'signed char + unsigned int'? Item 4 would then convert both operands "to the underlying unsigned type" {making the expression some 'unsigned' thing} "corresponding to the type of the operand with the underlying signed type" {making the expression some 'char' thing}, making the expression 'unsigned char'. Do I have that correct? Should that *be* correct?
This is an updated response as there was a missing rule in the last posting - it is highlighted in italic below.

i1 and uc have a different signedness and hence the expressions i1 | uc and i2 ? i1 : uc are not compliant with Rule 10.1.a. However the resultant underlying type can be deduced by extending the usual arithmetic conversion rules, as described in section 6.2.1.5 of ISO 9899:1990, to underlying types. They are described more fully at the end of this response.

&i1 and ip both have an underlying type of int *.

( i1 == i2 ) has a type of int, which is understood to be its underlying type. This is mentioned in 6.10.2 in the section on balancing conversions. There was discussion, whilst the guidelines were being drawn up, as to whether there should be an underlying type of Boolean, but it was felt that other rules sufficiently restricted the use of Boolean expressions

f has an underlying type of float.

Usual arithmetic conversion rules and underlying types

The existing rules in section 6.2.1.5 of ISO 9899:1990 apply to underlying types except the statements \"otherwise, both operands have type int\" can be replaced by
1. If both operands have the same underlying type, no further conversion is needed.
2. Otherwise if both operands have the same signedness, the operand with smaller magnitude is converted to the type of the other operand.
3. Otherwise if the operand with the larger magnitude is unsigned, the other operand is converted to the type of the larger magnitude type.
4. Otherwise, if the type of the operand with underlying signed type can represent all of the values of the type of the operand with underlying unsigned type, then the operand with unsigned type is converted to the type of the operand with signed type.
5. Otherwise, both operands are converted to the underlying unsigned type corresponding to the type of the operand with the underlying signed type.

\"signed char + unsigned int\" would then be caught by rule 3, which would convert \"signed char\" to \"unsigned int\".