Rule 12.1 deals mainly with operator precedence. For example, the following are exactly equivalent but the rule advises using the second form because it makes the intent absolutely clear:
However, it also mentions associativity of operators in its rationale and suggests using parentheses to control the order in which operations occur. In my opinion, it isn't helpful for Rule 12.1 to try and deal with associativity because Rule 10.1 does a better job of catching those instances where it matters. However, the 2004 rules are superseded by the 2012 ones so I don't think they will be receiving any further technical updates.
The problem with associativity is that in algebra, addition is associative, e.g.
but in C it's not necessarily the case. If a, b and c are all unsigned integer types and are either (a) all the same size, or (b) no wider than the int
type, then addition is associative. But if they are different unsigned integer types with one wider than int
then you can't guarantee that the result is independent of the order of operation. If they are signed types or floating-point types then you also can't guarantee associativity because of the possibility of overflows.
For example, suppose:
Code: Select all
unsigned int a = 1u;
unsigned int b = 65535u;
unsigned long c = 1u;
Consider the expression (a + b) + c on a machine in which int
is 16 bits wide and long
is 32 bits wide. The rules of C say that the program must behave as if
the addition in (a + b) is performed first and then c is added. So, (a + b) is evaluated in the unsigned int
type giving 65536. But 65536 doesn't fit in unsigned int
so according to the rules of unsigned types in C it's reduced modulo 65536 giving 0. The value is then widened to 32 bits and added to c giving a result with value 1 and type unsigned long
On the other hand the expression a + (b + c) on is evaluated as if the addition in (b + c) is performed first and then a is added. So, according to the C rules, b is first widened to 32 bits and added to c giving 65536 which happily fits in 32 bits. Then a is widened to 32 bits and added to 65536, giving a result with value 65537 and type unsigned long
. So, addition isn't necessarily associative in C.
There are a few other points to note:
- The order in which the operands a, b and c are evaluated is independent of the order in which the addition operations occur;
- An implementation only has to behave as if the rules of C are being obeyed; if the compiler is able to determine that the result cannot be affected by the order of operations then it is free to choose a different order.
I believe that your tool is flagging a violation of Rule 12.1 because you have mixed types, i.e.:
Code: Select all
ushort16 + ushort16 + unsigned int
You might find that casting your 1u to ushort16 type fixes the problem. But I'd say that you don't have a real issue here anyway because all your types are no wider than unsigned int
so the result can't be affected by the order of operation. If it were a problem then I'd expect Rule 10.1 to be flagged as would be the case if you changed your constant from 1u to 1uL for example.
That's all a bit complicated but I hope it helps.