12-11-2009, 09:42 AM
Fine, my example isn't relevant to the rule. Then please provide an example where failure to conform with rule 10.6 will lead to bugs, increase misunderstandings or confusion, or otherwise affect the safety of the system.
What does the U suffix solve then? If u16a doesn't underflow through the operation, the type of "100" doesn't matter. If u16a does underflow, how will you be aided by getting the result as an unsigned integer? Lets assume the programmer has written some suspicious code like this:
if((u16a - 100) > 32767)
Ok that rare scenario will cause problems (mainly because it is obfuscated, but let us ignore that for the discussion's sake). Now let us assume that 10.6 was not part of MISRA-C. How would we then make that code compliant?
First we have the advisory rule 12.11 "evaluation of constant unsigned integer expressions should not lead to wrap-around" explicitly banning the above code. But since it is only advisory, the user may ignore that rule. Then we have rule 10.1, forbidding any implicit casts on the complex expression u16a - 100. The underlying type of the expression is unt16_t, so in order to conform with rule 10.1 we must change the code to
if( (u16a - (uint16_t)100) > (uint16_t)32767 )
In this example, rule 10.6 is apparently superfluous. The example does however illustrate the importance of rule 12.11, perhaps that one should be made mandatory?
First of all, I just realized your original code violates MISRA 12.7 "Bitwise operators shall not be applied to operands whose underlying type is signed". If you do unorthodox, non-MISRA compliant operations on large hexadecimal constants close to INT_MAX and then threat the result as signed decimal values, yes of course your program will run amok. Doing so is unwise in three different ways: because of signedness, because of implicit conversions, but also because ISO C allows other forms of signedness formatting than two's complement (ISO 9899:1999 6.2.6.2). Your code assumes two's complement, and thus is relies on implementation-defined behavior, which you must explicitly document according to MISRA.
To sum it up, people mixing signed integers and hexadecimal notation are asking for trouble whether they follow 10.6 or not. This is why we have rule 12.7 - it is a very good rule.
This isn't relevant to the U suffix. The solution is the L suffix.
Quote:Consider for example, the expression "u16a - 100", an operation involving an unsigned variable and a constant of type signed int; if an int is implemented in 16 bits the result will be of type unsigned int. If an int is implemented in 32 bits the result will be of type "signed int" (and could be negative).
What does the U suffix solve then? If u16a doesn't underflow through the operation, the type of "100" doesn't matter. If u16a does underflow, how will you be aided by getting the result as an unsigned integer? Lets assume the programmer has written some suspicious code like this:
if((u16a - 100) > 32767)
Ok that rare scenario will cause problems (mainly because it is obfuscated, but let us ignore that for the discussion's sake). Now let us assume that 10.6 was not part of MISRA-C. How would we then make that code compliant?
First we have the advisory rule 12.11 "evaluation of constant unsigned integer expressions should not lead to wrap-around" explicitly banning the above code. But since it is only advisory, the user may ignore that rule. Then we have rule 10.1, forbidding any implicit casts on the complex expression u16a - 100. The underlying type of the expression is unt16_t, so in order to conform with rule 10.1 we must change the code to
if( (u16a - (uint16_t)100) > (uint16_t)32767 )
In this example, rule 10.6 is apparently superfluous. The example does however illustrate the importance of rule 12.11, perhaps that one should be made mandatory?
Quote:both constants will be considered to be of type 'unsigned int', the invert operation will invert 16 bit, the cast to 'long' will sign-extend the values to 0x00007FFFUL.
OK, it now depends on what you wanted in the first place, but at least both values are handled identically, and arguably "do what the programmer intended".
IMHO this is much better than without the suffixes.
First of all, I just realized your original code violates MISRA 12.7 "Bitwise operators shall not be applied to operands whose underlying type is signed". If you do unorthodox, non-MISRA compliant operations on large hexadecimal constants close to INT_MAX and then threat the result as signed decimal values, yes of course your program will run amok. Doing so is unwise in three different ways: because of signedness, because of implicit conversions, but also because ISO C allows other forms of signedness formatting than two's complement (ISO 9899:1999 6.2.6.2). Your code assumes two's complement, and thus is relies on implementation-defined behavior, which you must explicitly document according to MISRA.
To sum it up, people mixing signed integers and hexadecimal notation are asking for trouble whether they follow 10.6 or not. This is why we have rule 12.7 - it is a very good rule.
Quote:It would be nice if a compiler could/would warn about a situation like the use of 0x00008000 being used as a constant. By supplying the leading zeroes the programmer at least suggests that she/he intends to provide 32 bits of value. However, the compiler will still create a 16-bit unsigned integer. Here's where tools like PC Lint fill in the gap, if you let them
This isn't relevant to the U suffix. The solution is the L suffix.
<t></t>