Pointers Lesson Notes

From BenningtonWiki

Jump to: navigation, search

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.

Personal tools