This is a draft version of a MISRA C++ 202x rule proposed for public review.
MISRA Rule 8.2.2
Category: Required
Analysis Type: Decidable,Single Translation Unit
Amplification
This rule does not apply to functional notation casts that use curly braces or that result in a constructor call.
Rationale
C-style casts and functional notation casts raise several concerns:
- They permit almost any type to be converted to almost any other type without checks;
- They give no indication why the conversion is taking place;
- Their syntax is more difficult to recognize.
These concerns can be addressed with the use of const_cast
, dynamic_cast
, reinterpret_cast
and
static_cast
, which:
- Enforce constraints on the types involved;
- Give a better indication of the cast’s intent;
- Are easy to identify.
Exception
A C-style cast to void
is permitted, as this allows the intentional discarding of a value to be made explicit — for instance, the
return value of a non-void function call (see M23_007: MISRA C++ 2023 Rule 0.1.2).
Example
int32_t g();
void f1()
{
( void ) g(); // Compliant by exception
}
In the following example (which violates M23_090: MISRA C++ 2023 Rule 8.2.3), the C-style casts from a1
to the
non-const pointer a2
is more permissive than necessary. If the type of a1
is not A
, then the C-style cast to
a2
will compile, resulting in undefined behaviour. The equivalent const_cast
to a3
will not compile if
the type of a1
is changed.
struct A
{
A( char c);
};
struct B {};
void f1a( A x )
{
auto const & a1 = x;
A * a2 = ( A * )&a1; // Non-compliant
A * a3 = const_cast< A * >( &a1 );
}
void f1b( B x )
{
auto const & a1 = x;
A * a2 = ( A * )&a1; // Non-compliant
A * a3 = const_cast< A * >( &a1 ); // Ill-formed
}
void f2( int32_t x )
{
auto i = A( 'c' ); // Rule does not apply - constructor is called
auto j = int8_t { 42 }; // Rule does not apply - use of curly braces
auto k = int8_t ( x ); // Non-compliant - does not construct an object
} // of class type
Copyright The MISRA Consortium Limited © 2023