You've got some C-style struct use going on here which is bad form. Let's rewrite it to look like C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include <iostream>
using namespace std;
struct A {
char x;
int y;
};
int main() {
char p[12];
A *s = NULL;
s = (A*)p;
s->y = 2;
return 0;
}
|
That's better. Now,
(A*)p
says "take the object p, and pretend it is in fact an object of type pointer-to-A."
So,
s = (A*)p;
says "take the object p, and pretend it is in fact an object of type pointer-to-A, and then make s equal to that value."
So
s
now points at the char array. Why would you want to do this?
Essentially, you do this when you want to get around the compiler stopping you crossing type boundaries. Normally, the compiler would stop you, telling you that you cannot make a pointer-to-A point at something that isn't an object of type A. You do this when you want to insist on it.
In your example, it's completely unnecessary, In some other cases, it is necessary. For example, maybe you want to do your own memory allocation because new isn't good enough for you, so you set aside some memory first like this:
char* memoryStore = new char[1000];
This sets aside a thousand bytes for you. You could then use these thousand bytes however you like, without having to call
new each time; you can simply point at places inside it and cast the pointer to whatever type you like to use the memory. It comes with risks, of course; you have to make sure to construct the objects properly, and you mustn't lose track of where everything is, but that's programming for you - a series of trade-offs between safety and performance.
Perhaps you're using some hardware and you've been told that you must write values to a certain location in memory to interact with it (for example, controlling some LEDs), with each value occupying one byte. You decide to keep your values in a struct, to make it easy to work with:
1 2 3 4 5
|
struct LED_states{ // Note to self - ensure compiler packs these tightly. NO PADDING!
char LED_one;
char LED_two;
char LED_three;
};
|
The memory location is, for example, 0xFEEDBEEF.
LED_states* controller = (LED_states*) 0xFEEDBEEF;
Now you can use the pointer controller to set the LED states:
1 2
|
controller->LED_two = 1;
controller->LED_three = 0;
|
As a general rule in C++, someone somewhere has a use for everything and anything it can do, and as you get more programming experience, you'll start thinking of these things yourself. One popular use for pointer casting is polymorphism, which you'll definitely get to if you keep going.