jdl
jdl

Reputation: 6323

Why is my static_cast of a pointer failing?

Why is my static_cast of a pointer failing?

int iDog = 456;
int *piDog = &iDog;
long *plDog = static_cast<long*>(piDog); // invalid type conversion

long lDog = static_cast<long>(iDog);    // ok

long* plDog = (long*)(piDog); // this is OK too... very weird!! (Dynamic cast... and we aren't allowed to use this one in our coding standards)

This reference suggests it should be OK: https://en.cppreference.com/w/cpp/language/static_cast

Issue with Visual Studio C++?

Upvotes: 0

Views: 2378

Answers (2)

eerorika
eerorika

Reputation: 238281

long *plDog = static_cast<long*>(piDog); // invalid type conversion

Why is my static_cast of a pointer failing?

Because it is ill-formed. None of the rules of static_cast apply to the cast that you're attempting. It is an invalid conversion, as you mention in the comments.

A pointer to one object type may not be static casted to a pointer to another object type unless they are pointers to related classes, or when casting to/from pointer to void.

This reference suggests it should be OK: https://en.cppreference.com/w/cpp/language/static_cast

That reference suggests that the conversion you attempt is not OK.

long* plDog = (long*)(piDog); // this is OK too... very weird!!

This is a well-formed conversion. It's not "weird".

There are many conversions that explicit conversions (also called "cast notation" or "C-style cast") allow, and static casts do not allow. This is because static casts have (at least a semblance of) type safety while explicit conversions essentially ask the compiler to pretend that the type system doesn't exist.

Note that indirecting through plDog and accessing the object would result in undefined behaviour. As you can see, it was a good thing that you got the error.

and we aren't allowed to use this one in our coding standards

This is a good limitation to have. This will make it bit harder for your team to write bugs by mistakenly circumventing the type system.

Issue with Visual Studio C++?

No, the issue is that the program is ill-formed. The compiler is correct to inform you about the bug, and is not required to compile the program.


I recommend asking yourself: Why do you want to, or think that you need to do such cast?

Upvotes: 7

Chuck Walbourn
Chuck Walbourn

Reputation: 41047

TL;DR: If your cast worked, the language would provide no type-safety guarantees for pointers, and is a key part of the motivation for introducing the C++ style casts instead of sticking with the old-school C cast.

In the language of the C/C++ Standard, long* and int* are not "pointer-compatible". You can't implicitly convert a long* to an int* or vice-versa, so static_cast can't do it in a single cast.

The reasoning behind that is sizeof(long) is not always equal to sizeof(int) for all platforms. They are distinct fundamental types. This is true in general of all distinct C/C++ types even if they have an identical binary layout. They are only "pointer-compatible" if in the syntax of the language you declare the types to be related via implicit conversion.

You can use static_cast when converting from a void* to any pointer to an object type or vice-versa.

Therefore you can do this in two ways:

  • reinterpret_cast<long*>(piDog);

-or-

  • static_cast<long*>(static_cast<void*>(piDog));

Stylistically, the use of the reinterpret_cast is a lot clearer. In either case, the validity of the cast is architecture dependent and assumes sizeof(int) == sizeof(long) as well as having the same memory layout.

IOW This is safe for Windows x86 and x64 native, but may not hold for other platforms or CPUs. This is one of the reasons Windows x64 choose to use the LLP64 data model as explained in this blog post.

See cppreference for static_cast and reinterpret_cast

Upvotes: 0

Related Questions