I receive a pointer p to a struct S from C code and want to downcast it in C++ with
static_cast<S_extended*>(p)
where
S_extended is derived from S but just adds some methods to S so that the struct remains trivial and having standard layout (no virtual functions, no special functions, etc. are added).
No new data members are added into derived class.
Does such casting cause undefined behavior?
For example,
typedef struct S{
uint32_t data;
} S;
struct S_extended
: public S {
uint32_t getData(){return data;}
};
S s = {1};
uint8_t f(){
return static_cast<S_extended*> (&s) -> getData(); // UB ???
}
What you are attempting to do is UB in multiple ways. Let's start with the fact that down-casting to a derived class isn't possible as per C++23 [expr.static.cast] p2 if you don't have an object of the derived type.
Even if it was possible to
static_castin this case, you would immediately run into another form of undefined behavior. Up until C++20, this would be:- C++20 [class.mfct.non-static.general] p2
Sis not the same type asS_extendedor derived fromS, and you are calling a member function ofS_extendedfor an object of typeS. The behavior is undefined.In C++23, this requirement was generalized for member access
E1.E2:- C++23 [expr.ref] p8
Note that similar means
SandS_extendedwould need to be pretty much the same type, and they are not.Note: This C++23 change was made in CWG2535 Type punning in class member access