MISRA Discussion Forums

Full Version: Notional operations Rule 10.1
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Page 43 of MISRA C2 states:

The expression u32a + u16b +u16c is compliant but u16a + u16b +u32c is not compliant.

See also examples on page 44.

Surely this assumes the order of evaluation is left to right. Please could you clarify whether the guideline examples are correct?

Many thanks in advance.

Jonathan
On a 16 bit integer machine, the following happens. (Assume number represents the number of bits used for storage.)

Evaluation is left to right.

I have also changed the variables to u16a, u16b amd u32c.

u32c + u16a + u16b

u32c + u16a is evaluated in 32 bits unsigned.
x + u16b is added in 32bits unsigned.

Therefore, all operations have occured in one type.

But.

u16a + u16b + u32c

u16a + u16b is evaluated in 16 bits unsigned. Any overflow is handled by defined mod 65536.

x + u32c is evaluated in 32 bits unsigned.

There are therefore values of u16a, u16b and u32c for which

u32c + u16a + u16b is not equal to u16a + u16b + u32c

While the compiler's behaviour IS defined, the rule is intended to avoid such subtle differences.

Note that
(uint32_t) u16a + u16b + u32c is ok.

(uint32_t) u16a puts u16a into a 32 unsigned value.

x + u16b x is uint32_t, so is evaluated in 32 bit unsigned.

y + u32c is evaluated in 32 bit unsigned.

u16a + (uint32_t) u16b + u32c
(uint32_t) u16a + (uint32_t) u16b + u32c

would also work. The last line contains more than the minimum casting necessary to achieve consistant type.

I.e. consider

(uint32_t) u16a + u16b + u16c + ... + u16z + u32c

There is no need to clutter the code with a cast on every operator.

George
So it all appears to hang on the assertion "Evaluation is left to right."

Is there a reference for this?

Thanks in advance.

Jonathan
The C language DOESN'T define the order of evaluation of operands except in some circumstances (see paragraph 3 of Section 6.3 of the (C90) standard).

The standard DOES state that the precedence and associativity of operators are defined by the grammar (Section 6.3 footnote 35).

The actual order in which the compiler performs evaluations isn't specified but the result MUST, for all operand values, be the same as if the operations had been performed in accordance with the precedence and associativity rules.

I therefore think that I incorrectly asserted a left to right order.

u16a + u16b + u32c

is subject to unspecifed behaviour, and may compute the left-most addition in either 16 bit or 32 bit on a 16 bit machine.
Wouldn't that make both examples unspecified? If the order is right-to-left, then the first example would have the same issue.

At any rate, the expression falls under "complex expressions" in MISRA rule 10.1 and therefore it cannot rely on implicit typecasts.
So neither example is compatible, no matter the order of evaluation.
> The C language DOESN'T define the order of evaluation of operands except in some circumstances (see
...
> The standard DOES state that the precedence and associativity of operators are defined by the grammar
...
> I therefore think that I incorrectly asserted a left to right order.

There are several operations having an 'order' here. There is (a) the order in which the operands are inspected to decide what implicit conversions need to be performed and there is (b) the order in which operands are evaluated to obtain a value.

The order (b) is unspecified. However, the order (a) is specified by the syntax and in the case where the operands all have the same precedence it is left to right.

So you were correct to assert a left to right order when deciding what, if any, type conversions needed to be performed.
Derek_farn I don't mean to be rude or impertinent (maybe a little pedantic) but please would you cite reference(s) for your assertions (a) and (b).

Jonathan
JonM,

(a) http://c0x.coding-guidelines.com/6.5.html sentence 944

(b) http://c0x.coding-guidelines.com/5.1.2.3.html sentence 212 (ok, this is only an example and so is not normative). The chain of reasoning needed to work this out is rather long, perhaps one day I will write it down.

In the expression u16a + u16b * u32c the operands of the multiply have their types compared and converted appropriately, followed by the operands of the binary plus (because of the way that precedence binds them). Here the order happens to be right to left, but only because of the way that the expression has been written with the multiply on the right.
ISO C is wonderfully fuzzy when it comes to precedence rules...

That first link would be a copy of ISO C 9899:1999 chapter 6.5 "Expressions". The whole definition of the extremely important operator precedence rules in ISO C are found in a tiny subclause...

6.5 row 3:

"The grouping of operators and operands is indicated by the syntax.71) Except as specified later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation of subexpressions and the order in which side effects take place are both unspecified."

Tiny subclause in fine print:

"71) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same
as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the
expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in
6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators
(6.5.3), and an operand contained between any of the following pairs of operators: grouping
parentheses () (6.5.1), subscripting brackets [] (6.5.2.1), function-call parentheses () (6.5.2.2), and
the conditional operator ?: (6.5.15).
Within each major subclause, the operators have the same precedence. Left- or right-associativity is
indicated in each subclause by the syntax for the expressions discussed therein."

And there you have it, the very definition of the precedence rules every C programmer is expected to know. There is no other documentation in the standard over this.

In plain English, the operator precedence in ISO C is defined by the order the description of the operands are written in the document. You just need to check in what order they appear in that lovely section of 30 pages...