Well that is the correct thing to do. I guess you can't really complain to MISRA about C being crazy.
Well that is the correct thing to do. I guess you can't really complain to MISRA about C being crazy.
Rule 3-9-2 (which is only advisory) says Typedefs that indicate size and signedness should be used in place of the basic numerical types, but this doesn't prohibit use of size_t.
Is it? I can think of quite a few cases where using 'int' is fine; why is that a problem?
Sometimes you are working within the guaranteed bounds of an 'int' in the C standard, so portability isn't an issue. Sometimes you are mixing different types and want to capture intermediate values in the promoted type, which is dictated by the C standard. Sometimes you want to use the native machine word for a good reason. And sometimes it is just easier to read and reason about (printf-like conversion specifications, code that interfaces with POSIX APIs frequently, etc).
It's much less error prone to use fixed size types, especially since approximately all computers are now 32 or 64 bit.
I once lost hours on an Arduino project exactly because of this. I was using the SD card library, and there was an infinite loop bug. Turned out to be because most Arduinos (at the time) are 16 bit, but I was using a 32 bit one. The code had been written using `int` but also assumed that int was 16 bits!
The code was less portable because of the "portable" int sizing system. It didn't work at all with other sizes, whereas if it had been written using uint16_t it would have worked fine.
You can say "well they made a mistake", but remember we're talking about MISRA. Avoiding mistakes is the whole point.
I'm fully willing to believe that MISRA-C contains a lot of silly, unnecessary rules, but IMO this isn't one of them. If typing out uint32_t, etc is too long, then you can always create an alias.
Security teams at our company have told me this too but I absolutely disagree. If you're going to write in C, and you don't want your variable to overflow, then you should use a type that doesn't have defined overflow semantics.
The reason for this is that it makes it easier to find bugs, because you want to discover wrong behavior rather than just define it to do an arbitrary wrong thing. You can do this with UBSan.
In fact, as long as it's okay for your code to crash, I endorse shipping it with UBSan turned on. (Presumably this isn't the case for a car MCU though. Don't ask me what to do there.)
It's a problem when your toolchain or target changes, and assumptions you were making (explicitly or implicitly) about 'int' now fail in difficult to understand ways.
Today we have int16_t et al., so this is much less of an issue.
*) IME "know" is often merely a "believe".
**) Not sure that even if you have a MISRA checker that has a suitable inference, it is allowed to discard alarms on this kind of violation. I wrote MISRA test cases for something for a suitable powerful checker/analyzer, but I can't remember this detail anymore.
Also, IME it obscures bugs in your code if you're forced to overspecify things, because now someone reading it has to determine if all those explicitly specified details are actually correct or not.
Your second point doesn't make any sense. Someone reading `int` has to determine if that is actually correct or not too.
If you assign an int32_t to an int16_t because you know the actual range of values fits at that point, later readers don't necessarily know that. (And it can change.)
If they're both int, there's no possible problem.
To put it another way:
> If they're both int32_t, there's no possible problem.
The second statement contradicts the first - int16_t is too specific and hides errors, but an arbitrary range is not?
The arbitrary range is actually capable of being correct. int16_t is almost never "correct", since it's larger than the actual range of values.
It can also be said to be an over-optimization, since on some platforms like x86 it's easier to deal with 32-bit values than 16-bit ones.
I'm not in the mood of discussing this or convincing you otherwise. If you made up your mind to use int over intWhatever_t then so be it. We're not working on the same project and I suppose you're not building anything that might kill me.
Conversely, incorrect assumptions about size/size/capacity can lead to subtle run-time bugs.
Or just use int32_t and let the compiler fail if your Toolchain does not have that. Then just write an appropriate header to add it (with the correct checks) ;)