Pointers to classes and casts

Here:

1
2
3
4
5
6
7
8
9
10
class B {
public:
   virtual void Test(){}
};
class D : public B {};

void f(B* pb) {
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
}


The function f tries, on the first line/command, converting the pb object, pointing to the base class B, to a pointer to the derived class D and then uses it to initialize pd1, with run-time check. The second line does the same for pd2, without any check.

1) Do pointers, irrespective of what they point to whether it's an object of a built-in type or user-defined type, have the same size?

2) Does a pointer to a user-defined type object point to the first byte of that object?

More question on the code later on.
Last edited on
1) Do pointers, irrespective of what they point to whether it's an object of a built-in type or user-defined type, have the same size?

Not necessarily, pointer sizes and formats are determined by the hardware.

2) Does a pointer to a user-defined type object point to the first byte of that object?

Yes
1) generally, yes. A long time ago, on dos era machines, there were 'near' and 'far' pointer types (far was twice as big an integer as near, I think it was 16 and 32 bit). I have not seen a setup like that in a very long time. Everything I have worked on in recent years has one pointer size fits all. You can look this up for your target platforms, though, if you think your code will need to run on something other than a standard PC or typical server box configuration. I doubt you will see this issue outside of embedded computers.

2) not only yes, but if you make 2 identical structs or classes and add one data item to the bottom of one of them, you can treat the matching parts as the same on most systems; I don't know of any where they would bork up alignment or positioning, and I don't know that this is ensured, but in practice, it generally works and I have used it in C a little as a poor man's quasi polymorphism. Its as if the compiler stuffed the data part of objects into an array of bytes in the order it sees them in, top down. (Which is, actually, a lot like how it ends up, though again watch that padding etc). Screwing with objects directly at this level is not advised apart from learning exercises, unless you have an extreme need and can show a tangible advantage.
Last edited on
Thank you both.
embedded computers
Do you mean that inside embedded devices we may/can have pointers having different sizes? (If the language used in C or C++)
Last edited on
can have pointers having different sizes?
'Can' -- yes, it's theoretically allowed per the standard. I don't know of a particular embedded architecture that does this, but it's possible.

But, for instance, Visual Studio's compiler guarantees 32-bit pointers on 32-bit builds, and 64-bit pointers on 64-bit builds; that is, it makes guarantees stronger than what the C++ standard itself states.

Does a pointer to a user-defined type object point to the first byte of that object?
This is true, but note that it's not always allowed to manipulate this data through the pointer. That is technically only allowed if the struct/class is in "standard layout" (although I imagine most compilers would be OK with it anyway). There was a discussion some of us had about this months ago, but I can't find the link at the moment.
https://en.cppreference.com/w/cpp/language/data_members#Standard_layout
2) Does a pointer to a user-defined type object point to the first byte of that object?
Yes, but the first byte of the object might not contain what you think it does. For example, the first byte of your "D" object is probably the beginning of the base class B instance that it inherits from. If you want to access the members from the pointer, don't do the arithmetic yourself, just use the member names and let the compiler worry about where it is.
In this:
1
2
3
4
5
6
7
8
9
10
11
12
class B {
public:
   virtual void Test(){}
};
class D : public B {
void print(std:: string st) {
std::cout<<st<<'\n;
};
void f(B* pb) {
   D* pd1 = dynamic_cast<D*>(pb);
   D* pd2 = static_cast<D*>(pb);
} 


1) If pb == 0, that means pb is a null_ptr then there won't be any issue with converting it to a pointer to either D or B, and for both the result will be alike, right?

2) The conversions are unlike if pb is a pointer to the class B, ie., the dynamic-cast returns zero (failure) while static-cast does the task carelessly, all bets are off. right?
Last edited on
Do you mean that inside embedded devices we may/can have pointers having different sizes? (If the language used in C or C++)

------------
it could. Mostly, because of the aforementioned dos :)
http://www.jkmicro.com/Flashlite186.html
I don't know what other systems have it. I saw a brief mention in a forum that its due to attached devices that have their own direct addressing, so the attached device can have pointers into it of a different size than the main CPU uses. There were no examples of this in action, though, and the post was 10 years + old.

regardless, its a possibility that exists largely in historical / legacy systems or very odd (and extra small where every byte counts) systems. Its relatively safe to assume a pointer on a particular system has one size and not several, esp if you are targeting large (lets say more than a gb of ram) common, popular systems (desktops, servers, laptops, phones, tablets, ...) and not off the beaten path. I don't know what goofball mainframe OS might do if you encounter an antique (Y2K or before) one, or one that has newer hardware but the older software due to the common upgrade to death approach.
Last edited on
Thank you.
How about my last questions above, please?
2) You can't always assume this. For instance for virtual classes there is usually a vtable pointer at the beginning of a class.
Last edited on
You could read the manual:

https://en.cppreference.com/w/cpp/language/dynamic_cast

You could also test this yourself.

For question 2, why do you think the dynamic cast will fail?

Edit:

Also be careful with if(pb == 0):

Rather explicitly test with if(pb == std::nullptr)

Presumably one would want the pointer to not be a null pointer.

Also would be good if you supplied a use case for this, rather than a theoretical XY problem.
Last edited on
> Do pointers, irrespective of what they point to whether it's an object of a built-in type or user-defined type, have the same size?

The standard guarantees this:
A prvalue of type “pointer to cv T”, where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The pointer value is unchanged by this conversion.
https://eel.is/c++draft/conv.ptr#2


> 2) Does a pointer to a user-defined type object point to the first byte of that object?

The first byte of the object-representation of that object. (Every bit in the object-representation may not be part of the value-representation of the object).
Thank you. I try to form a new thread for the latter question to get through the problem separately.
Topic archived. No new replies allowed.