dragoncoder posted:
Consider the code
class A {
private:
int a;
};
int main(void) {
A x;
int* ptr = (int*)&x;
*x = 10;
return 0;
}
I understand that I can not change the private attributes of a class,
but what does standard have to say about the code above?
I got lost lower down in the thread so I'll start again here.
Someone was trying to do something akin to the following:
std::string object("Hello");
std::string* p = (std::string*)(int*) &object;
And they implied that the above is perfectly okay, such that the programmer
can go on to use "p" as follows:
cout << *p;
Firstly, let's break that code up and turn it into:
std::string object("Hello"); //Line 1
int* p_int = (int*) &object; //Line 2
std::string* p_str = (std::string*) p_int; //Line 3
cout << *p_str; //Line 4
On Line 2, we are casting an "std::string*" to an "int*" and storing the
result in a variable of type "int*". The Standard gives no guarantee
whatsoever that an "std::string*" can be cast or stored accurately as an
"int*". It is possible that, on a particular platform, that the cast may
work perfectly, but it is not guaranteed to work, and so is not 100%
portable.
On Line 3, we are casting an "int*" to an "std::string*" and storing the
result in a variable of type "std::string*". The first thing to note here is
that the Standard gives no guarantee whatsoever that the value in "p_int" is
valid -- it may be corrupt. Even if we cast it back to an "std::string*",
we've no guarantee that it points to the object called "object". It's quite
like going from "double" to "int" and then back to "double" -- you won't
have the original double's value.
Line 4 might print "Hello", then again, it might print the New Testament if
you've got the bible open in Adobe Acrobat at the same time.
Then someone posed the argument that you can cast a pointer to an "int" and
back to the original pointer type and that it will work perfectly. Here's
some sample code:
std::string* p = new std::string("Hello");
int num = (int)p;
std::string* k = (std::string*)num;
cout << *k;
delete p;
The Standard gives no guarantee whatsoever that the above code will work.
The Standard says that you can cast a pointer value to an integral type, and
then back to the original pointer type, but the final value will only be
legitimate if the integral type had enough bits to store the pointer value.
Nowhere in the Standard are we given any guarantee that any of the integral
types are large enough to hold any of the pointer values; so even if you use
an "unsigned long", you still can't be sure it will work. It's not 100%
portable, and so, it has no place in the realms of Standard C++.
-Tomás