The Pointer

NOTE: This is just because a lot of beginners need a grasp on this concept.

WHAT IT IS
----------

Pointers are addresses. The can be assigned, or made to "point to" another memory location. They are a powerful concept that is not well understood by many users of C. Their use can make code more efficient, more readable, and more functional.

HOW TO USE IT
-------------

Pointers are declared by using the following template (assuming T is a type):
 
T *var;

Of course, some prefer the convention of:
 
T* var;

but these modifications are in the personal opinion of the user, since the compiler ignores the whitespaces in a declaration (that don't seperate a type and the first variable).

The address of a normal variable can be assigned to a pointer as follows:
1
2
3
T *ptr;
T var;
ptr=&var;

This works because the ampersand (&) will take the address of var, and assign the value to the pointer, which itself holds an address.

Pointers to pointers can be made. And so can pointers to those, but they are hardly useful.

The asterisk (*) can dereference a pointer.
1
2
3
4
5
6
T *ptr;
T var, var2;
ptr=&var;

var2=*ptr;
*ptr+=var2;


The last two statements effectively assign var2 the value of var (because the dereference operator tells the machine to follow the pointer to the variable), then adds var2 to var (the same as doubling var). Since the pointer was dereferenced to the same location as var, all operations on the dereferenced pointer will take effect on the variable it points to.

Often, to signify the state of not pointing to anything, a pointer will be assigned the value of 0. This pointer is the null pointer. It is illegal to dereference a null pointer.

Pointers can be declared constant by putting the keyword const before the asterisk in the declaration:
 
T const *var;


Do NOT confuse this with
 
const T *var;

which defines var to point to a type of constant T. Constant pointers must be initialized. Arrays, in fact, are constant pointers.

The space allocated for pointers is the space necessary to hold a memory address. This is usually an unsigned long.

Pointers can be redirected to multiple targets. For example:
1
2
3
4
5
6
7
8
T *ptr;
T var, var2;

ptr=&var;
//Do some stuff with var

ptr=&var2;
//Do some stuff with var2 


Pointers have their own kind of arithmetic: adding or subtracting values (let's say X) actually causes a shift in the address equal to X*sizeof(T). This is how arrays dereference (the expression a[x] is really *(a+x), which works because arrays are constant pointers). Multiplication and division are not allowed.

A pointer to any arbitrary type T must have the declaration T * OR one of the special types, void *. Void pointers (not to be confused with null pointers) can be assigned an address to any value. Because of this, pointer arithmetic on void pointers is illegal, as is dereferencing them. You can dereference and perform arithmetic on a casted void pointer, though.

A pointer definition doesn't implicitly span to each member in a declaration, you need an asterisk before each pointer variable.

WHY YOU NEED THEM
-----------------

ARRAYS, ARRAYS, ARRAYS!!! Every array is a constant pointer, so it is pretty crucial to have this feature.

Functions normally are passed copies of their parameters. By passing addresses (and defining the function to receive a pointer), the caller's value can be modified. Passing of this type is called pass by reference.

Pointers are crucial to the processing of strings. Every C String is a character array, and hence a constant pointer to a character.

They are also necessary when making linked lists and using dynamic memory allocation. Using pointers for dynamic memory allocation means you can:
-use the same pointer for multiple seperate memory spaces.
-assign this value to any other pointer with the same type or a void *.
-Define an arbitrarily long range to be put under a single pointer. This is the basis of arrays.

GOING FARTHER
-------------

Go ahead, try a few pointings. Remember, you have to cast a void pointer to use it.

Pointers are used internally on several occasions. Not a program doesn't have a pointer in it, because functions are pointers to the compiled code for that function in their data segment (yes, even main). Find other such uses.

Your reply is valued! Please give questions and comments below!
Thank you,
Graham Northup
Last edited on
Looks like a great tutorial. One thing though: You mention very briefly that pointers can be used for dynamic memory allocation. Maybe you should go into more detail about this point - what does dynamic allocation mean/how does it differ from other allocations? Any examples (with malloc() or new, as appropriate), etc. etc.
>>Often, to signify the state of not pointing to anything, a pointer will be assigned the value of 0. This pointer is the null pointer.

Wrong, a pointer is just like another variable with only the difference it points another memory location. A pointer is normally created in local memory while its pointed-to memory is in the heap.
As noted in other (dynamic allocation) post, a local variable is created in stack which is volatile and tends to hold garbage if not initialized. Hence you should not assume that an uninitialized pointer holds a ZERO.

Attempt to access an unitialized pointer is dangerous and the program will mostly crash (with a core dump).
It is better to initialize a pointer declaration always with a NULL unless it should be of a legal value/address.

for example:

T *myPtr1 = NULL;
T *myPtr2; //no guarantee of a legitimate value

free (myPtr1); // or delete myPtr1; -- no harm/crash
free (myPtr2); // or delete myPtr2; -- CRASH

Check it out. Good luck :)







@satm2008:

I don't agree that the statement was wrong. He didn't say that an uninitialized pointer was null, but that value was often assigned to a pointer. Though it can not be said too often how important it is to initialize pointers.

Your example looks like C code. It may still be valid C++, but we should try to make examples the way we typically write C++. I think this is better:

1
2
3
4
5
T *myPtr1 = 0; // probably keyword null_ptr in the next version of the standard
T *myPtr2; //no guarantee of a legitimate value

delete myPtr1; // no harm/crash
delete myPtr2; // CRASH 


BTW: Are you sure it is even OK to call free(NULL) in C?
>> BTW: Are you sure it is even OK to call free(NULL) in C?
Yes, I checked it out. It's OK.
A pointer and its declaration (and its behaviour) almost same in C and C++, where as C++ offers more features to initialize it propertly (with their constructures and allowing new to call them).

And about NULL and 0, NULL is always pre-defined 0 (ZERO) value.
T *myPtr1 = NULL
or
T *myPtr1 = 0 or same :)

And about the rest, you check it :)


NULL is not necessarily the same as 0 (zero).

NULL is usually defined as the lowest memory address. This may well be 0 (zero) in an architecture that has unsigned address space but not on an architecture that uses a signed address space.

Although the standard dose state:
1
2
3
4
5
6
7
A null pointer constant is an integral constant expression (expr.const) rvalue of integer type
that evaluates to zero. A null pointer constant can be converted to a pointer type; the result is
the null pointer value of that type and is distinguishable from every other value of pointer to
object or pointer to function type. Two null pointer values of the same type shall compare
equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single
conversion, and not the sequence of a pointer conversion followed by a qualification
conversion (conv.qual).


and the C99 standard
1
2
3
4
An integer constant expression with the value 0, or such an expression cast to type void *, is
called a null pointer constant.[55] If a null pointer constant is converted to a pointer type, the
resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any
object or function.
Last edited on
> A pointer and its declaration (and its behaviour) almost same in C and C++, where as C++ offers more features to initialize it propertly (with their constructures and allowing new to call them).

Teaching beginners to use "malloc" and "free" in C++ is plain wrong.

> NULL is always pre-defined 0 (ZERO) value.

It might (unlikely) be "(void*)0", which cannot be implicitly converted to T. However, it's not a question of whether it works, but whether it's "good practice", and I think the current trend in C++ is going towards "0" instead of "NULL" (at least until nullptr is available).

I think the common definition is something like:
1
2
3
4
5
#if C++
#def NULL 0
#else C
#def NULL ((void*)0)
#end 


@Grey Wolf:
The first quote, Is that the current standard (03), or the specification for the upcoming nullptr?
Ropez,
The first quote is from a disuction of the need for nullptr in the C++0x standard but is more or less from the 2003 standard. (Section 4.10 Pointer conversions)
Topic archived. No new replies allowed.