4

I have this function:

void InitS(unsigned int &numS){
   // this function returns a container for unsigned int
   // but it has a cast for int
   numS = props.numOfS();
   if (numS > 0) {
        ..
   }
}

It compiles but gives me this MISRA warning:

MISRA-C++ Rule 4-10-2 (required): Literal zero (0) shall not be used as the null-pointer-constant.

Now, if numShots were a "real" pointer I could have changed 0 to NULL. But numShots is reference and I should treat it as it was an int.

What does MISRA want and why?

sharptooth
  • 167,383
  • 100
  • 513
  • 979
or.nomore
  • 915
  • 1
  • 10
  • 20
  • 2
    looks like a bug to me. – PlasmaHH Mar 05 '13 at 15:42
  • If that is the correct representation of the code, then I agree, there is no error there. – Mats Petersson Mar 05 '13 at 15:43
  • Are you sure `if (numS > 0)` is the line producing the warning? – Angew is no longer proud of SO Mar 05 '13 at 15:43
  • That's what it says, it points to the 'if' line – or.nomore Mar 05 '13 at 15:45
  • What you have posted seems to be perfectly valid code. See this example: http://ideone.com/OBJ9EV – LihO Mar 05 '13 at 15:54
  • 2
    @LihO That link is utterly irrelevant. The whole point of MISRA is to be stricter than conventional compilers. – Konrad Rudolph Mar 05 '13 at 15:58
  • Is the argument really `unsigned int &` or could it be `unsigned int*`? If the argument is a pointer the printing of the warning could make sense. On the other hand, I don't quite agree that to be an issue. – David Rodríguez - dribeas Mar 05 '13 at 15:59
  • @KonradRudolph: I wanted to point out, that I don't see any reason why some compiler would "complain" about this code, no matter how strict it is. – LihO Mar 05 '13 at 16:06
  • @LihO How does your comment point that out? Let's say I invent MISRA-superstrict, making the use of pointers and references illegal altogether. A compliant compiler would then reject the above code, and rightfully so, no matter how many proofs you have of other compilers not complaining about it. – us2012 Mar 05 '13 at 16:12
  • @DavidRodríguez-dribeas: Agreed. Specifically, it's usually a mistake to use `NULL` at all in C++, since to readers it looks like a pointer but it is actually an integer. Maybe MISRA avoids that problem with another rule to detect when `NULL` is used in a context that doesn't convert it to a pointer type. I don't know because I've never used MISRA. – Steve Jessop Mar 05 '13 at 16:24
  • I thought NULL was always 0 in C++? Making C++ different from C where NULL is more magical and fuzzy. [Stroustrup's FAQ](http://www.stroustrup.com/bs_faq2.html) claims that NULL is always 0. So you'd think this would matter a lot more in C than C++. Yet _MISRA-C_ has no such rule about NULL being explicitly expressed as pointer type. So I'd really like to hear the rationale behind this rule 4.10.2 in MISRA C++. – Lundin Mar 06 '13 at 07:34

3 Answers3

4

Since nums is an unsigned int, you will need to compare to 0U, where the appended 'U' indicates the literal is an unsigned int, versus a signed int without.

This traps my team all the time. We don't understand why a zero needs to be marked as unsigned.

Also, you are not dealing with pointers. The function signature, unsigned int&, indicates that the variable will be passed by reference,not by pointer. You will be modifying the original object, not a copy.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • I still don't understand why misra complaining about not using a null pointer constant if what you say is actually the problem? – or.nomore Mar 05 '13 at 16:10
  • MISRA is very strict type checking, more than the normal compiler options. Variables should not be compared to pointer constants. Pointers should not be compared to numeric literals. – Thomas Matthews Mar 05 '13 at 17:30
  • So 0 is signed int? Then why MISRA thinks its null pointer constant? This seems really weird behavior since NULL implemented in C++ as ((void*) 0), so why MISRA won't complain if numS was signed int? – or.nomore Mar 06 '13 at 06:52
  • This seems not related to the issue described, the rule that integer literals must be unsigned seems to be a separate issue entirely. And why accept this as answer if it didn't answer the question? – Lundin Mar 06 '13 at 07:36
  • But it did answer the question – or.nomore Mar 06 '13 at 07:54
  • @or.nomore But the rule says that literal zero shall not be used as null pointer constant. `0U` is just as much literal zero as `0`. This does not explain the error you got. Particularly, it does not explain why you can't compare a reference variable against literal zero. – Lundin Mar 06 '13 at 13:34
3

Let me start by saying that I have no experience of MISRA-C++, but plenty of MISRA-C.

MISRA-C have some concerns about type safety that apply to MISRA-C++ as well. One such concern is that no implicit type promotions should occur. This is a valid concern, implicit type promotions are hard to understand and lead to bugs. Most C and C++ programmers surprisingly don't even know how implicit type promotions work. To educate programmers about this and to protect against such bugs, there are numerous MISRA rules regarding implicit type conversions/promotions.

  • One such rule enforces the 'u' suffix to all integer literals. The rationale behind the rule is to clarify that large literals close to the maximum int value are unsigned, for example the type of the literal 0x80000000 is not obvious to the reader. (I personally consider that rule superfluous and somewhat misguided, since all implicit conversion dangers are already covered by other rules.)

  • There is also another rule stating that pointer checks against NULL should be explicit. You aren't allowed to write if(ptr), you should rather write if(ptr!=NULL). The rationale is readability and type safety.

  • And there is apparently this rule that pointers should not be compared against a zero literal. I don't understand the rationale behind this, supposedly they are afraid that you mix up pointers and plain integer variables. They apparently have made the decision to deviate from Bjarne Stroustrup's ambition to de-mystify null pointers in C++. According to Stroustrup, NULL and 0 are always equivalent in C++ (though C++11 will have a nullptr keyword solving this mess once and for all).

None of the above mentioned rules have anything to do with the code in your example! You are comparing a reference against a zero literal, which is perfectly safe. A MISRA checker may complain about missing 'u' suffix, but your checker did not.

My conclusions are:

  • Your MISRA-C++ checker is faulty and gives incorrect errors.
  • The particular MISRA-C++ rule against literal zero does not seem to make any sense. You should raise a deviation in your MISRA implementation against this rule and ignore the rule entirely, until someone can provide a rationale for it.
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

I could be wrong, I'm not really seasoned in programming, and probably the answer is a bit late, but I think your MISRA-C checker is thinking "he's comparing a variable of type "reference" to a literal constant, so he must be checking for a NULL reference" even though it's not really valid for References, but you can try assigning the return value of the function props.numOfS() to a new variable then doing the assignment to the variable referred to by numS in a another line while doing the comparison on the new variable.

i.e.

void InitS(unsigned int &numS){
   unsigned int foo;
   foo = props.numOfS(); //this function returns a container for unsigned int but it has a cast for int
   numS = foo;
   if (foo > 0) {
        ..
   }
}

Check if it's complaining after that.