Why don't I understand pointers??

noobman

[H]ard|Gawd
Joined
Oct 15, 2005
Messages
1,475
Pointers and me never quite got along. I've read so much about them, but I've yet to really encounter a situation where I've thought that it was quintessential to use a pointer.


I had a bit of a problem with my first job in C. When I started I would write code... upon code reviews the guys would always say "OK this looks fine, but why didn't you use a pointer here, here, and here?"


Could somebody here please attempt to explain pointers to me?
I think my problem comes from examples. It's easy to create an example that shows how a pointer works, but it's difficult to create an example where it really makes sense to use one. Towards the end of that job I was pretty proficient with using pointers (especially with pointers to character arrays to edit strings, oh C...) but it's been a while and I found myself quite rusty while trying to help a friend.


Here's what I know (remember) thus far:

& is the "address of" indicator.

Code:
int i = 2;
int* j;

j = &i;
That will set my pointer, j, to the address space of i. If I were to look at the literal values, i would equal 2, and j would equal 0x00FF or something like that.

AFAIK a pointer is just a value that tells your program to go to a place in memory. With that being said, I see two good uses for a pointer:

1) Passing a value to a function by reference instead of by value
2) Saving on some memory space instead of keeping duplicate values stored


When else should I use a pointer, and why?
To be honest, pointers are really the only thing that keep me away from using C++ more often. When I see them in code I can understand them, but I have a hard time writing with them and I find that they scramble my brain.

I can use pointers, and I can understand how a pointer is being used in code when reading it... but I just can't for the life of me understand *why* a pointer was used!


So please... I ask that you help me solve my pointer problem once and for all.
 
You absolutely need pointers to use the heap (runtime memory allocation), which any reasonably large application will likely require. They're also essential to data structures like linked lists, trees and stack/queue structures (though since these are almost always dynamically allocated anyway, it's kinda secondary with the first point). I'm shocked you were able to work in C professionally for some time and didn't gain an integral grasp of pointers, as I doubt you'll find much C code in the wild that doesn't use and require them extensively.

In C++ you need pointers very rarely compared to C. With STL, reference types and the object oriented heap you can pretty much avoid them entirely if you want. And probably should in most cases.
 
Last edited:
one of the problems with pointers you probably hit was something along the lines of:

int i = 555;
int *j = &i;
return j;

oh noes! something else is where I was..... and now everything is hosed.
Because i is on the stack, and only exists while the current function is executing.
 
You absolutely need pointers to use the heap (runtime memory allocation), which any reasonably large application will likely require. They're also essential to data structures like linked lists, trees and stack/queue structures (though since these are almost always dynamically allocated anyway, it's kinda secondary with the first point). I'm shocked you were able to work in C professionally for some time and didn't gain an integral grasp of pointers, as I doubt you'll find much C code in the wild that doesn't use and require them extensively.
/quote]
It was a summer work term (I'm still a student, you see...) for about four months. My job function was to develop a test harness for ab embedded devices. I'd say that I spent 60% of my time shell scripting, 30% of my time interfacing with the device and automating processes, and 10% in C. I had to add some functionality to the device that didn't already exist.


I understand how pointers work (and why they're necessary) with linked lists. So far I've read and (hopefully) understood all of your posts, but I still don't

In C++ you need pointers very rarely compared to C. With STL, reference types and the object oriented heap you can pretty much avoid them entirely if you want. And probably should in most cases.
I've seen people make extensive use of pointers in areas where I didn't think they should exist. My assumption is that they were seeing something that I didn't,or that they were using a pointer when they didn't need to be using one.
 
I've seen people make extensive use of pointers in areas where I didn't think they should exist. My assumption is that they were seeing something that I didn't,or that they were using a pointer when they didn't need to be using one.

Tons of C++ code out there does use pointers, but it's basically unnecessary except for low-level interfacing tasks. If you're writing a 'true' C++ application without calling any C libraries and using mostly object-oriented constructs, the language provides better ways to do almost everything you'd use pointers for. But since C++ is (almost) a superset of C, lots of C coders migrate but never break their old habits. If you're writing new code from the ground up, you can (though I wouldn't really recommend it) get away with knowing basically nothing of pointers at all and still do useful work. That's not really true with C.

Not that when I refer to 'using pointers' here, I mean doing anything other than treating them as references, much like the way array references in C are 'really' pointers. It's a little bit more explicit in C++, but you can still get away with a very basic idea of what they actually are storing.
 
I disagree that in C++ you rarely need pointers. I will describe 2 exmaples:

Code:
class foo
{
   virtual void bar() = 0;
};

now when use this interface in a child class and want to access the child like it is a foo (as is the case if foo has several child classes), then I am out of luck without pointers. You can't instantiate an abstract class.

next, imagine this scenario

Code:
class foo
{
   class bar
   {
   };
};

if memory serves me correctly, bar cannot access foo's members without a reference (i.e. a pointer) to a foo object.

one last instance where pointers are handy. Imagine I have a device at memory-mapped location 0x0000FFFF that reads 4 bytes, or spits 4 bytes out at me. without code like this
Code:
unsigned int x = *(unsigned int)0x0000FFFF);

I can't ever talk with the device! On some systems, this is even how one communicates with the registers. A pointer would come in handy for when I want to change the address and don't want to change a bunch of hard-coded values.

I use these techniques daily. Please realize that just because you don't use a technique doesn't meant that someone else doesn't either.
 
Your first two examples can use references instead of pointers in most cases, though there are cases where you do need to use pointers. Virtual classes are pretty quirky.

Anyway I'm not really saying pointers are useless, just that you can do a heck of a lot without them, where in C you run into a brick wall pretty quickly.
 
Your first two examples can use references instead of pointers in most cases, though there are cases where you do need to use pointers. Virtual classes are pretty quirky.

Anyway I'm not really saying pointers are useless, just that you can do a heck of a lot without them, where in C you run into a brick wall pretty quickly.

point taken :)
 
If you're writing a 'true' C++ application without calling any C libraries and using mostly object-oriented constructs, the language provides better ways to do almost everything you'd use pointers for.
Why do you think references are better than pointers?
 
It's easy to create an example that shows how a pointer works, but it's difficult to create an example where it really makes sense to use one.

It might make sense for a URIParser in C.

Examples (of result, not parsing, and just showing a couple parts of the URI)

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* copyPart(const char* const start, const char* const end) {
    const size_t len = end - start;
    char* s = malloc(len + 1);
    if (s == NULL) {
        exit(EXIT_FAILURE);
    }
    strncpy(s, start, len);
    s[len] = '\0';
    return s;
}

int main() {
    /* Parse URI without allocating copies of each part */
    const char* const uri = "http://example.org/";
    const char* const proto_start = uri;
    const char* const proto_end = uri + 4;
    const char* const host_start = uri + 7;
    const char* const host_end = uri + 18;
    /* Copy a part only when needed */
    char* proto = copyPart(proto_start, proto_end);
    char* host = copyPart(host_start, host_end);
    printf("_%s_\n_%s_\n", proto, host);
    free(proto);
    free(host);
    return EXIT_SUCCESS;
}
 
Pointers and me never quite got along. I've read so much about them, but I've yet to really encounter a situation where I've thought that it was quintessential to use a pointer.
This will come as you gain experience.

It's easy to create an example that shows how a pointer works, but it's difficult to create an example where it really makes sense to use one.
Not to abuse you to prove my point, but had you learned assembly before you learned a higher-level language, pointers would be second-nature to you and their use and application would be intuitive.

Indeed, a pointer is a variable that holds an address. The type of the pointer tells you what the type of the value at the target address is expected to be. The address of an integer is generally the same as the address of a floating-point number, but manipulating the address might mean something different.

Your list of applications for pointers is correct, but there are a couple of important applications which you miss.

One is the manipulation of arrays. An array is a data structure in memory where you can assume that element n+1 of the array is immediately after element n, and element n is immediately after n-1. Since pointers are addresses, you can find elements in arrays just by moving the pointer along. This makes pointers very useful for strings, but they're also useful for moving around in other types of arrays.

Let's consider this example:

Code:
#include <stdio.h>

void main()
{
	int array[] = { 9, 27, 81, 243, 729, 0 };

	for ( int n = 0; array[n] > 0; n++ )
	{
		printf("element %d is %d\n", n, array[n] );
	}

	for ( int *ptr = array; *ptr > 0; ptr++ )
	{
		printf("element at 0x%8.8X is %d\n", ptr, *ptr );
	}
}

The first loop should be pretty familiar to you. It uses the index "n" to walk through the array, and quits when it finds an element of the array that's not greater than zero. It prints each element of the array, then, telling us what the numeric index is:

Code:
element 0 is 9
element 1 is 27
element 2 is 81
element 3 is 243
element 4 is 729

The second loop is a little more curious, though. It uses a pointer. It initializes it to point at the first element of the array. It will quit the loop in the same circumstances -- if it finds that the pointer is looking at an element that is not greater than zero. It increments the pointer each iteration of the loop.

This loop relies on the fact that each element of the array is stored immediately after the previous element. We don't know the ordinal index in the array, so the loop prints out the actual pointer value. It also prints the integer that the pointer references. That output looks like this:

Code:
element at 0x0012FF20 is 9
element at 0x0012FF24 is 27
element at 0x0012FF28 is 81
element at 0x0012FF2C is 243
element at 0x0012FF30 is 729

Of course, on your comptuter, the pointer numbers will be different. But certainly, we still print the values of the array.

You can see that the addresses each increment by four. That's because a single integer takes four bytes. The compiler knows that "ptr" points to a four-byte integer, so ptr++ increments ptr by four instead of just by one.

It turns out that, for some non-trivial code, you'll actually find that the second loop is faster than the first becuase of some assumptions the compiler can make about the pointer, but can't make about the array.

Another common application of pointers is implementing dynamically allocated structures, and length unknown-structures. Pointers are often used for strings because they're arrays of characters. But they're also often of a size that's not known until runtime, so it's best to dynamically allocate the memory. If the memory is dynamically allocated, it's location isn't known until the allocation is made -- again, at run time.

When you take a data structures class, you'll also learn about interesting data structures that are more complicated than arrays. Linked lists, for example; or trees. These structures let you store variable amounts of data in ways that are efficiently accessed depending on your needs. It's very common that some particular element of such a structure will use one or more pointers to refer to other elements of the structure. In a binary tree, for example, a given node will point at the sub-tree that contains items which are less than the current item, and the sub-tree containing items that are greater than the current item.

I hope that helps. Let me know if you have any questions.
 
Back
Top