Pointer help

Started by
10 comments, last by Cornstalks 12 years, 6 months ago
struct Player
{
int health;
float healthRegen;
int *armor;
};
int armorvalue = 75;

Player MyPlayer = { 10, 20.0, &armorvalue };
Player *g_pMyPlayer = &MyPlayer;
Player **g_ppMyPlayer = &g_pMyPlayer;

int main()
{





MyPlayer.health; // health value
*MyPlayer.armor; // armor value

g_pMyPlayer->health; // health value
*g_pMyPlayer->armor; // armor value






return 0;
}

1.) how do i obtain the health value and armor value using the double pointer variable called **g_ppMyPlayer
2.) Also how are these implemented without using the -> operator and only using parenthesis and *?
Advertisement
1. (*g_ppMyPlayer)->health
2. p->x == (*p).x so (*(*g_ppMyPlayer)).health

Each * 'peels off' one layer of the pointer, and -> can be used to simplify the common (*ptr).member pattern.
[TheUnbeliever]
*(**g_ppMyPlayer).armor;


@TheUnbeliever, you are missing an *. Its a pointer to a pointer to a reference, thus two levels of onion peeling.
@TheUnbeliever, you are missing an *. Its a pointer to a pointer to a reference, thus two levels of onion peeling.


What? It's a Player** - a pointer to a pointer to a player. We dereference once to get a Player* and again to get a Player (or use -> to get the member directly). &v gives you a T* where T is the type of v.

In any case, a pointer to a reference isn't a meaningful concept, as far as I know. A reference is, for all intents and purposes, the original object. You'd just get a plain ol' T*.
[TheUnbeliever]

[quote name='Serapth' timestamp='1318892876' post='4873673']@TheUnbeliever, you are missing an *. Its a pointer to a pointer to a reference, thus two levels of onion peeling.


EDIT: Argh, just realized my mistake, sorry TheUnbeliever, I missed the you were dealing with health in your example, not armor.


What? It's a Player** - a pointer to a pointer to a player. We dereference once to get a Player* and again to get a Player (or use -> to get the member directly). &v gives you a T* where T is the type of v.

In any case, a pointer to a reference isn't a meaningful concept, as far as I know. A reference is, for all intents and purposes, the original object. You'd just get a plain ol' T*.
[/quote]

No, a ref is more akin to a const pointer to the original object, now when passing a value by reference, it feels like you are using a native object, but when assigning a pointer to a reference, you are essentially creating a const pointer to the objects location.


What this sample is dealing with is a pointer to a pointer to an object. Therefore to access it, you need to ** twice, once to resolve the pointer to a pointer, and once to resolve the pointer to the pointed at object. Then in this particular case, since the structure member ( armor ) again is a pointer, to use "." syntax, it needs to be *'ed once again. More simply, just try to compile the code you gave him, without another dereference your code will not work. Since he asked to deal with "." access, you need a double dereference first.

Ok, that came out poorly. What I am saying is, your example either needs to be:

*(*g_ppMyPlayer)->armor
or
*(**g_ppMyPlayer).armor // if you want to use . instead of ->



As to the OP, by parentheses, do you mean square brackets?

So you want to access your pointer like
g_ppMyPlayer[0][0].armor?
I'm trying to understand reading complex pointers and would like to know the many different ways each of these can be implemented using -> , * , and []
Just to be clear: there are no references in the above code, at all. If you create a reference, and then create a pointer from this reference, you do not need an additional use of the indirection operator (*). That is, the following code is correct.

[source lang="cpp"]int main()
{
int x = 0;
int& x_ref = x;

int* x_ptr = &x_ref; // points to x
*x_ptr = 1; // x is 1
}[/source]

However, it is certainly the case that you need an additional indirection to access the value pointed at by the armor member above, because this is itself a pointer. So you'd have something like *((*g_ppMyPlayer)->armor) which is ugly as sin. The member itself - the pointer - is still accessed exactly the same as health: (*g_ppMyPlayer)->armor.


I'm trying to understand reading complex pointers and would like to know the many different ways each of these can be implemented using -> , * , and []


p->x is identical to (*p).x
p is identical to *(p+i)
[TheUnbeliever]
1.) are the following equivalent




*MyPlayer.armor;
*(MyPlayer).armor;
*(MyPlayer.armor);
MyPlayer.armor[0];


(*g_pMyPlayer).armor
*(g_pMyPlayer->armor)
g_pMyPlayer[0].armor

*(**g_ppMyPlayer).armor;
*(*g_ppMyPlayer)->armor;
g_ppMyPlayer[0][0].armor;


im wanting to understand how to fully manipulate pointers in doing what i want and being able to read others code when they use different styles of derefernceing.

@TheUnbeliever, you are missing an *. Its a pointer to a pointer to a reference, thus two levels of onion peeling.


Just to be clear: there are no references in the above code, at all.

FYI, I think that's where the misunderstanding is coming from between you too :)


1.) are the following equivalent

Most of them, no. I think what would help you is really understanding how pointers actually work -- what they really are. They just point to a memory address. Somewhere in memory. Anywhere in memory. And that's all a pointer stores. Is a memory address.

You have to use * to access the memory that is stored in that memory address that the pointer points to. -> is shorthand for (*pointer).member; so you can do pointer->member instead. That is, -> is used to access the members of a data structure from a pointer, just like . is used to access the members of a regular data structure. -> and * are very different, seeing as * has nothing to do with the data structure's members.

pointer[x] is the same as *(pointer + x), like has been said. That is, it takes the memory address stored in the pointer, advances it by x units (so now its a new memory address, x units away from the original memory address), and then it deferences the pointer to access the actual data stored in the memory at that advanced location.

For the record, pointer[0] is the same as *pointer (that is, *(pointer + 0) is the same as *(pointer)), but you shouldn't just mix the two casually. [] is used for arrays, and * is used for non-arrays; using * on an array or [] on a non-array is something you should only do if you really, really know what you're doing.

I remember watching this video years ago, and it helped me understand things.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Answers in line below:

1.) are the following equivalent


All the 1st ones are the same. The . takes precedence over *, so all of these you are getting the value pointer at by armor

*MyPlayer.armor;
*(MyPlayer).armor;
*(MyPlayer.armor);
MyPlayer.armor[0];


These below are not the same, see my comments after each line

(*g_pMyPlayer).armor
// The above value will be the address of armor, you need to do this:
// *(*g_pMyPlayer).armor

*(g_pMyPlayer->armor)
// the above is fine

g_pMyPlayer[0].armor
// This one is the same as the 1st. The value will be the ponter to armor, you need to do this:
// *g_pMyPlayer[0].armor or
//

The below are almost the same, (ie, you get the value of the data armor points to) the last one is not.

*(**g_ppMyPlayer).armor;
*(*g_ppMyPlayer)->armor;
g_ppMyPlayer[0][0].armor;
// This one is almost right, you still need to go one deeper with *
// *g_ppMyPlayer[0][0].armor;
// however, I would not recommend using ** like this



im wanting to understand how to fully manipulate pointers in doing what i want and being able to read others code when they use different styles of derefernceing.
[/quote]


My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement