Safer explicit type conversion
In C there is just one syntax for explicit type conversion: the cast expression, with syntax (T) e where T is a type and e is an expression. This notation covers a multitude of sins. It can be used to do any of the following, or more than one at the same time:
- Convert one numeric type to another
- Reinterpret a pointer to one type as a pointer to another type, an integral type as a pointer type, or vice versa
- Remove the const or volatile attribute of the expression’s type
Although C++ still supports the C-style cast syntax, it also provides better type-conversion operators with more specialized meanings:
- static_cast<T>(e) is provided to convert between numeric types
- reintrepret_cast<T>(e) is provided to convert between pointer types, or between integral and pointer types
- const_cast<T>(e) is provided to remove const and/or volatile from the type
There is also dynamic_cast<T>(e) but that is not relevant unless we’re allowing classes to inherit from each other.
These C++ type conversion operators have significant advantages over the C cast notation. First, they make it clear what category of type conversion we intend to do. This prevents us from intending to do a type conversion in one category but accidentally doing a conversion in a more dangerous category; or inadvertently discarding const-ness or volatility along with the conversion we intended. Second, it is easy to pick out the more dangerous categories when reviewing source code. For example, the conversions that reinterpret_cast does are generally more dangerous than the ones performed by static_ cast. Third, the operand of the type conversion appears in brackets, removing the possibility of precedence errors. Fourth, you can easily search source text for instances of these type conversions.
Therefore, my “C with little bits of C++” language for developing critical systems includes the following rules:
- You are allowed to use the static_cast, reinterpret_cast and const_cast features of C++.
- You are not allowed to use the C cast notation.
For critical system development, reinterpret_cast and const_cast should generally be avoided. If you have been writing in C and using a MISRA compliance checker, then MISRA C 2004 rules 11.1 through 11.5 restrict what you can do with C casts having the semantics of reinterpret_cast and const_cast. To get equivalent checks when you use the C++ constructs, you’ll need to use a MISRA C++ compliance checker, or (preferably) ban the use of reinterpret_cast and const_cast completely.