|
This rule seems to be commonly deviated from by most people I have spoken to. I have given it thought, but I still cannot understand how it would lead to more secure programs.
The only argument provided by MISRA for this rule is that “the type of an integer constant is a potential source of confusionâ€. Yes it is confusing, but only from a theoretical point-of-view, namely when you are determining what implicit type conversions that are done on the integer constant. That is, during a "scratch your head while learning C" session. During actual programming, you don't need to think about this.
I can't come up with one single scenario where leaving out the “U†suffix will lead to bugs or unintended behavior. Can anyone make such an example? If one integer in the operation is signed and the other is unsigned, and they are both of the same size, the "usual arithmetic conversions" will make sure both are unsigned. Consider the following example:
result = -1 - 10;
In this example, the type of -1 is "signed int" and the type of 10 is "int". If "int" is treated as signed by the compiler, there will not be any problems as both operands are then signed.
If "int" is treated as unsigned, then the operand -1 will be converted to unsigned, that is, to the value 65535 (assuming 16-bit system). The result of the expression will then be 655535 - 10 = 65525, which may not be the result the programmer expected. However, this will not lead to a bug! Because we aren't done with that line.
If "result" is of signed type, then the result 65525 will be converted to signed during the assignment, making it -11, which is the expected result.
If "result" is of unsigned type, the code does not make sense. If you try to stuff signed constants into a unsigned variable, no U suffix will save you.
MISRA fails to name a case where the lack of a “U†suffix would cause bugs. Integer constants are by their nature constant, and therefore deterministic. ISO C ensures that they are of the right size and signedness. It all boils down to what type the result is stored inside. If the type of the expression happens to be of different type than the variable, an implicit typecast will be done upon assignment to correct this.
Rule 10.6 also states that the implemented sizes of integer types is a reason why the U suffix should be used. I fail to see how this is relevant to the use of the U suffix. The example says that 40000 will be int or long depending on system... this has nothing to do with signedness at all. The example says that 0x8000 is possible signed in a 32-bit environment... so what? It is still a positive number in 32 bit. And you won't notice the signedness of a hex number until you represent it in a decimal format, and then it is up to you whether you want to display it as signed or unsigned.
Also, integer constants are never subject to the integer promotions, as they are always "int" or "long", so no need to worry about that either.
Further, writing “U†all over the source code is not common practice among programmers. It causes much more confusion than the hidden signedness of integer constants and worst of all, it makes the code harder to read. In addition, the MISRA-C document in itself is filled with examples where MISRA themselves do not even follow this rule. I can easily come up with countless examples, just open a random page and you will likely find it. The rule is simply too rigid and not practical to use in reality.
Though perhaps there exists a case when the lack of this suffix will lead to bugs? If not, I don't see any reasons keeping this rule.
|