The power of pointers. Just starting out.

Hello. I am very new to programming in general. I'm using the Handmade Hero videos on Youtube plus some other videos and a book. The book lists pointers as an advanced topic, but I've been jumping around it as I need to in order to figure out what's going on with Handmade Hero as best I can. So I realize some may think I'm getting ahead of myself when trying to understand pointers to their fullest extent, but I don't mind trying to take it in.

My question is about pointers and how to get them to be as useful as they are supposed to be. Some of my confusion comes from the fact I can write this:

int Test;
int *TestPointer;
int ChangeMe;

Test = 50;
TestPointer = &Test;
ChangeMe = *TestPointer;

int Test2;
int ChangeMe2;

Test2 = 50;
ChangeMe2 = Test2;

I can achieve the same result using ChangeMe2 = Test2, so there must be something that's going way over my head when it comes to pointers.

If anyone could give me some tips in super laymens terms it would be appreciated. Even among the advanced topics, pointers seem to be the only thing that is causing me problems. So if I can get it in my head it would clear a big road block.

Thanks for your help.
Well once you assign value to ChangeMe/ChangeMe2, there are really no differences what you do.

It's easier to show why pointers are useful with functions:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void f1(int Value)
{
  Value = 2;
}

void f2(int* Value)
{
  *Value = 2;
}

int X = 1;
f1(X);
printf("%d\n", X);
int* P = &X;
f2(P)
printf("%d\n", X);


Think about what happens in these functions, and try to see if you understand what will be printed out from each printf. Pointer doesn't reserve memory for value it points to. It always reads or writes to location it points to. So any change to value will be immediately available to anybody who keeps pointer to this value. It's all about how you organize memory. Passing pointers around to different functions (like GameState in Handmade Hero) allows you to change same memory locations without making copies everywhere.

Edited by Mārtiņš Možeiko on
Ok just looking at that, before running it, I'd guess the first printf prints 1 because you pass 1 to f1, change it to 2, but don't return a value. The second printf would return a 2 since you are passing a pointer to f2, which f2 uses to change the value that is being pointed to, even though you still don't return anything.

I ran it through VisualStudio and that's what happened. What I was doing didn't make much sense.. using a pointer inside just one function. So I see what you mean about using them with many functions.

This helps it click a little more. Thanks.. I'll keep playing around with them.
The primary utility of pointers comes more when you are operating on

A. Large collections of things, and
B. Things which might be reinterpreted in different ways.

For example, in Handmade Hero, we have the platform layer allocating a large block of memory, and then the game using pointers to subdivide it out into pieces that it wants to interpret in specific ways. This sort of thing is very easy and natural to do when you are comfortable working with pointers.

- Casey

Edited by Casey Muratori on
I'll do my best to explain it line by line, hopefully this will help you figure out what part you are not understanding.

1
int Test

Here you define a variable (of size int), this means Test stores a value somewhere on memory.
1
int *TestPointer;

Here you define a pointer (that can point to something of size int), this means that it stores an address on memory.
1
int ChangeMe;

Another int just like test

1
Test = 50;

Here you set Test to 50, this finds the address in memory (it doesn't matter where, the C compiler does this for you) and it changes the value at that memory to 50
1
TestPointer = &Test;

First lets look at the Right side of this statement "&Test." The & Opperator retrieves the address of a variable. Whenever I write & in code I think "address of" in my head. so the right side of the equation is "Address of Test." So TestPointer now contains an address in memory. This address will stay the same no matter what you do to Test. If you write "Test = 30" TestPointer will not change still the same address, that address just holds 30 now instead of 50.

1
ChangeMe = *TestPointer;

Now lets look at the Right side again. The * Operator (in an equation such as this line) means The value at this address. So *TestPointer translates to "The value at the address contained in TestPointer." So in this situation you can write ChangeMe = Test instead of ChangeMe = *TestPointer; because, they mean the same thing, Test is the value at some address, and *TestPointer is that same value. So ChangeMe was set to 50 in this line, it doesn't retain the fact that it was set to a dereferenced Pointer (*TestPointer), it just cared what the value was. If you added a new line after this that changed the value or Test, or changed the address of TestPointer; ChangeMe will not change. It will still be 50, it's now it's own variable.

1
2
3
4
5
int Test2;
int ChangeMe2;

Test2 = 50;
ChangeMe2 = Test2;

Hopefully I explained it well and you can see how these 4 lines of code accomplish the exact same result as your first segment of code. Infact the whole thing could be boiled down to ChangeMe2 = 50. Once you set it it doesn't care how it got 50, it's just 50.

You could even write something like this
1
2
3
4
5
int Test;
int ChangeMe;

Test = 50;
ChangeMe = *(&Test);

This again does the same thing as the other segments of code, it sets ChangeMe to 50. First the part in parenthesis (&Test) retrieves the address of Test. Then the * outside the parenthesis looks at the value of that address.

I hope this was readable, I don't always write the clearest explanations. A good way to learn about pointers is to use the Watch Window in Visual Studio.

Edit:
I re-read your original post and realized I am an idiot. It seems you know how they work you were asking Why, my mistake.

Edited by Reece H on