I was camping with my friend and (urgh) my parents and I brought C++ For Dummies, because that's my "game ideas" notepad plus it's helpful if I'm writing code in my head when I'm bored. He borrowed it and kept complaining about the pointers part. He still complains about pointers to this day. I realized maybe pointers aren't as easy to understand as you'd think, even though I understood them easily (just the way my brain works... and because hot people understand pointers better ^^)
This code isn't all complete because I'm on a keyboard in switzerland and typing's annoying on a changed keyboard. Plus the TAB key doesn't indent.
Alright so here goes.
A pointer is essentially just a vairable containing an address. Nothing else. Whether you declare a pointer using a variable, or create it using an address yourself, it's still just a 4-Byte address (UINT32). That being said, let's look at pointer declaration and initialization.
Code:
int nPointed_at = 5;
int* pnPointed_at;
pnPointed_at = &nPointed_at;
++(*pnPointed_at);
*pnPointed_at = 10;
int nPointed_at = 5; - Simple. Declares a signed 32-bit integer with the value 5. It's convention to begin integer names with n
int* pnPointed_at; - Declares a 32-bit number that will contain the address of an int. It's convention to begin pointer variable names with p.
pnPointed_at = &nPointed_at; - Gets the address of nPointed_at, and store it in pnPointed_at. Now pnPointed_at contains the address of nPointed_at (AKA where it's stored in memory, like a street address. Addresses begin at 0x00000000 and go to 0xFFFFFFFF in a 32-bit processor)
++(*pnPointed_at); - *pnPointed_at translates to
the variable at the address in pnPointed_at, or
the variable pointed at by pnPointed_at, so basically you could replace *pnPointed_at by the thing at the address in there, or nPointed_at. the "++" operator increases the thing pointed at by pnPointed_at by 1. You'll notice I used brackets. I always do that in case something takes precedence where I forgot it does. In this case, it doesn't matter (I think).
*pnPointed_at = 10; - set the thing pointed at by pnPointed_at to 10 (decimal), or 0xA (hex).
Who the *bleep* cares?
That's right, I said *bleep*. *bleep*ing deal with it, you *bleep*ing *bleep* of *bleep*.
Okay, so that's how to declare and use a pointer. What's the point? (no that wasn't a bad pun.. at least, not intentionally). Pointers can be passed to functions, declared so you can edit specific memory, etc. Please consider the following (eww.. bill nye the science guy reference.. ah well.. stupid science teacher)
Code:
void change_the_value(int nValue)
{
nValue = 6;
}
int main()
{
int n = 5;
change_the_value(n);
}
this declares a signed 32-bit integer with the value 5. Then it passes this integer to a function, which changes the value to 6 - theoretically. Actually the function creates a NEW variable called nValue and copies the contents of n into it. It then changes the value of nValue to 6, and then exists the function. The value passed (n) didn't actually change, because it just got copied. You could declare n globally and then try
Code:
int n;
void change_the_value()
{
n = 6;
}
int main()
{
n = 5;
change_the_value();
}
I don't even know if that works in C++ (as I said earlier, I'm in a different country.. no compiler), but either way, it's not a great solution. n is only used inside main, so declaring it outside doesn't technically create problems, but it makes the code annoying to use and reread. I personally like the pointer version...
Code:
void change_the_value(int* pnValue)
{
*pnValue = 6;
}
int main()
{
int n = 5;
change_the_value(&n);
}
There. In the change_the_value function, we create a new int pointer called pnValue, and copy the ADDRESS of n into it, then change the value at that address (which is n) to 6.
Now you can pass without fully copying a variable (although in this case, you would copy 4 bytes either way), keep arguments with your functions. AND (this makes it useful over the global-declaring method), you can pass different values and change each one of them, which a function which changes a certain variable can't.
Code:
void change_the_value(int* pnValue)
{
*pnValue = 6;
}
void change_the_copied_value(int nValue)
{
nValue = 6;
}
int main()
{
int n = 5;
int a = 7;
int b = 8;
change_the_value(&n);
change_the_value(&a);
change_the_copied_value(b);
}
in the end, n and a are both 6, and b remained 8, because only its copy was changed. BE SURE TO PASS ADDRESSES PROPERLY! if I said
Code:
...
change_the_value(n);
...
or
Code:
...
change_the_copied_value(&b);
...
then we would've passed n to the function (I'm pretty sure that'll actually create a compiler error), which would then think we were pointing at the address 0x00000005, and change the value there, which might be the "do you want to sign ownership of your house over to microsoft?" variable address.
in the second case, we would copy the address of b into nValue, say 0x00400000, and then change the value of the variable from that to 6. It would have no effect on that code (because we didn't change anything at the address, we just changed a value inside a variable), but would still give undesired results if the function was more complex.
Can you have pointers to pointers?
I'm glad you asked, Kevin (if that's actually your name, I'm not a stalker... even the judge ruled that I'm not).
Yup. I've actually used them. The declaration & initialization is pretty much the same.
Code:
int nValue = 5;
int* pnValue = &nValue;
int** ppnValue = &pnValue;
*pnValue = 6;
++(**ppnValue);
Declare a variable. Declare a pointer to that variable. Declare a pointer to a pointer to a variable. Add two cups flour. Bake at 375 for 20 minutes. Change the thing pointed at by the first pointer to 6. Increase the thing pointed at by the thing pointed at by the second pointer by 1. It's a lot harder to understand in text format than in code format. It's actually applicable though. For instance, you might have a pointer to an HP value that moves around every game. BUT you might have a pointer that contains the address of the pointer to the HP value. Even though your HP pointer changes, the "base pointer" (as I call it.. as do others), still contains its
dynamic address, and then you could go
Code:
int* hp_pointer;
int** base_pointer = (int**)0x12345678;
hp_pointer = *base_pointer;
*hp_pointer = 999;
or
Code:
int** base_pointer = (int**)0x12345678;
**base_pointer = 999;
This assumes your base pointer is always stored at the address 0x12345678. It assumes the address 0x12345678 contains the address of the pointer to your HP. I don't know if this syntax works (no compiler), but it's something like that, because I used it for my Final Fantasy Tactics Advance DLL (the base_pointer + hp_offset was the address of the hp_pointer. Oh and it's on this site, under I think the Gameboy SP forum).
This isn't a complete reference, it's something I typed up when I got bored. To learn more, read some tutorials online, or obtain some books.
Teh Robot