From 7427fa135a30428e43ece063ef73d10bd3a8c430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Wed, 26 Feb 2020 00:00:01 +0000 Subject: [PATCH] c++ typecast --- README.adoc | 7 ++ .../cpp/static_dynamic_reinterpret_cast.cpp | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 userland/cpp/static_dynamic_reinterpret_cast.cpp diff --git a/README.adoc b/README.adoc index 10fe1c9..af32a9d 100644 --- a/README.adoc +++ b/README.adoc @@ -14644,6 +14644,13 @@ https://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-sta http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf +[[cpp-type-casting]] +==== C++ type casting + +link:userland/cpp/static_dynamic_reinterpret_cast.cpp[] + +https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used/60414256#60414256 + === POSIX Programs under link:userland/posix/[] are examples of POSIX C programming. diff --git a/userland/cpp/static_dynamic_reinterpret_cast.cpp b/userland/cpp/static_dynamic_reinterpret_cast.cpp new file mode 100644 index 0000000..d9d5761 --- /dev/null +++ b/userland/cpp/static_dynamic_reinterpret_cast.cpp @@ -0,0 +1,75 @@ +// https://cirosantilli.com/linux-kernel-module-cheat#cpp-type-casting + +#include + +struct B1 { + B1(int int_in_b1) : int_in_b1(int_in_b1) {} + virtual ~B1() {} + void f0() {} + virtual int f1() { return 1; } + int int_in_b1; +}; + +struct B2 { + B2(int int_in_b2) : int_in_b2(int_in_b2) {} + virtual ~B2() {} + virtual int f2() { return 2; } + int int_in_b2; +}; + +struct D : public B1, public B2 { + D(int int_in_b1, int int_in_b2, int int_in_d) + : B1(int_in_b1), B2(int_in_b2), int_in_d(int_in_d) {} + void d() {} + int f2() { return 3; } + int int_in_d; +}; + +int main() { + B2 *b2s[2]; + B2 b2{11}; + D *dp; + D d{1, 2, 3}; + + // The memory layout must support the virtual method call use case. + b2s[0] = &b2; + // An upcast is an implicit static_cast<>(). + b2s[1] = &d; + std::cout << "&d " << &d << std::endl; + std::cout << "b2s[0] " << b2s[0] << std::endl; + std::cout << "b2s[1] " << b2s[1] << std::endl; + std::cout << "b2s[0]->f2() " << b2s[0]->f2() << std::endl; + std::cout << "b2s[1]->f2() " << b2s[1]->f2() << std::endl; + + // Now for some downcasts. + + // Cannot be done implicitly + // error: invalid conversion from ‘B2*’ to ‘D*’ [-fpermissive] + // dp = (b2s[0]); + + // Undefined behaviour to an unrelated memory address because this is a B2, not D. + dp = static_cast(b2s[0]); + std::cout << "static_cast(b2s[0]) " << dp << std::endl; + std::cout << "static_cast(b2s[0])->int_in_d " << dp->int_in_d << std::endl; + + // OK + dp = static_cast(b2s[1]); + std::cout << "static_cast(b2s[1]) " << dp << std::endl; + std::cout << "static_cast(b2s[1])->int_in_d " << dp->int_in_d << std::endl; + + // Segfault because dp is nullptr. + dp = dynamic_cast(b2s[0]); + std::cout << "dynamic_cast(b2s[0]) " << dp << std::endl; + //std::cout << "dynamic_cast(b2s[0])->int_in_d " << dp->int_in_d << std::endl; + + // OK + dp = dynamic_cast(b2s[1]); + std::cout << "dynamic_cast(b2s[1]) " << dp << std::endl; + std::cout << "dynamic_cast(b2s[1])->int_in_d " << dp->int_in_d << std::endl; + + // Undefined behaviour to an unrelated memory address because this + // did not calculate the offset to get from B2* to D*. + dp = reinterpret_cast(b2s[1]); + std::cout << "reinterpret_cast(b2s[1]) " << dp << std::endl; + std::cout << "reinterpret_cast(b2s[1])->int_in_d " << dp->int_in_d << std::endl; +}