Pointers Lesson Notes
From BenningtonWiki
Every variable has a place in RAM where it's stored, and you use & to get its address. It's called the address-of operator, and it works like this:
int main(void) { int x; printf("0x%08lx\n", &x); // print the address of the variable 'x' in RAM return 0; }
When I run this, I get:
0xbffffab8
Which is way up there in memory, around the 3 billion mark. How it got up there is another discussion (VM, stacks, runtime architectures, etc.). If I could open up the RAM on my machine and look in while this program was running, I could look at the four bytes beginning at 0xbffffab8 and see what the value of x is. It's right there. In RAM.
Check this out. I'll add another variable to the program. See if you understand the output:
int main(void) { int x, y; printf("0x%08lx\n", &x); // print the address of the variable 'x' in RAM printf("0x%08lx\n", &y); // and 'y' return 0; }
When run:
0xbffffab8 0xbffffabc
See how the address of y is four bytes above x? The compiler places variables together in RAM, just like that. If I looked inside RAM I'd see them sitting right next to one another. Sure, I call them 'x' and 'y' but to the microprocessor they're just bytes in RAM.
Perhaps you see that addresses are just numbers as far as the microprocessor's concerned. I can print the address as a decimal number if I wanted to:
int main(void) { int x; printf("%u\n", &x); // print the address of the variable 'x' in RAM; this time in decimal return 0; }
When run:
3221224120
The only difference with this program is the formatting string. The address isn't different and whether you think of it in hex or decimal it's just a number. It's common to format addresses in hex and most programs and debuggers do it this way.
Just to drive home the point that addresses are simply numbers, I can do this:
int main(void) { int x, y; y = &x; printf("0x%08lx\n", y); // print the address of x return 0; }
Now look at this:
int main(void) { int x; int *p; p = &x; printf("0x%08lx\n", p); // print the value of p (which is the address of x) return 0; }
The variable p is a pointer to an integer. The * in front makes it so. This is a new kind of variable type. In one real sense, p is just another integer variable that can hold a number (like that 3221224120 from above). x is a variable that can hold a number; p is a variable that can hold a number. But by telling the compiler that it's a pointer, I'm saying that I intend to use it to hold an address, and that opens the door to a whole new world of C magic.
Be sure you get that p is simply assigned the address of x. Run it and see for yourself.
Now I want to use p in its pointerly way. This is important:
int main(void) { int x; int *p; p = &x; x = 12; *p = 13; printf("%d\n", x); // print the value of x return 0; }
What's x going to be when it's printed? The line:
*p = 13;is the key. By prefixing p with an asterisk, I'm saying I want to mess with the variable at the address that's in p. In other words, I'm not messing with the value of p but with the variable that p is pointing to. p is assigned the address of x, which is that big number (0xbffffab8 or such), so I end of messing with x. This is called dereferencing the pointer. When I dereference a pointer, I'm manipulating the variable that it's pointing to.
As Eben pointed out, "dereferencing" sounds like a misnomer. The way he sees it, what's going on is that I'm dealing with what p is referencing. Perhaps it should be called referencing. I don't know. For half my life it's been "dereferencing" and it could just as likely be called "kevin" and I'd buy it.
