Pointers and Arrays (C++)

Pointers
For a type T, T* is the type "pointer to T". That is, a variable of type T* can hold the address of an object of type T/. For example:

Pointers to arrays and pointers to functions need a more complicated notation:

The fundamental operation on a pointer is //dereferencing//, that is, referring to the object pointed to by the pointer. This operation is also called //indirection//.

No object is allocated with the address 0. Concequently, 0 acts as a pointer literal, indicating that the pointer doesn't refer to an object. Always make sure to assign a variable for a pointer to point to before you use it, or initialize it to 0.

Arrays
For a type T, T[size] is the type "array of size elements of type T". The elements are indexed from 0 to size - 1. The number of elements of the array must be a constant expression. If you need variable bounds, use a vector.

Multidimensional arrays are represented as arrays of arrays, but are best avoided outside low-level code. For example:

String Literals
A string literal contains one more character that it appears to have; it is terminated by the null character '0'. The type of a string literal is "array of the appropriate number of const characters". If we want a string that we are guaranteed to be able to modify, we must copy the characters into an array:

A string literal is statically allocated so that it is safe to return one from a function.

Pointers into Arrays
The name of an array can be used as a pointer to its initial element. For example:

Taking a pointer to the element of one beyond the end of an array is guaranteed to work. This is important for many algorithms. However, since such a pointer does not in fact point to an elelemt of the array, it may not be used for reading or writing. The result of taking the address of the element before the initial element is undefined and should be avoided.

Navigating Arrays
Efficient and elegant access to arrays (and similar data structures) is the key to many algorithm. Access can be achieved either through a pointer to an array plus an index or through a pointer to an element. For example, traversing a character string using an index,

is equivalent to traversal using a pointer:

The prefix * operator dereferences a pointer so that *p is the character pointed to by p, and ++ increments the pointer so that it refers to the next element of the array.

Subtraction of pointers is defined only when both pointers point to elements of the same array. When subtracting one pointer from another, the result is the number of array elements between the two pointers (an integer). One can add an integer to a pointer or subtract an integer from a pointer; in both cases, the result is a pointer value. If that value does not point to an element of the same array as the original pointer or one beyond, the result of using that value is undefined.

Arrays are not self-describing because the number of elements of an array is not guaranteed to be stored with the array. This implies that to traverse an array that does not contain a terminator the way character strings do, we must somehow supply the number of elements.

Array of pointers
Declare an array of pointers to objects:

Allocate memory for an array of pointers dynamically:

Pointer to Void
A pointer to any type of object can be assigned to a variable of type **//void*//**, a void* can be assigned to another void*, void*s can be compared for equality and inequality, and a void* can be explicitly converted to another type. Other operations whould be unsafe because the compiler cannot know what kind of object is really pointed to. To use a void*, we must explicitly convert it to a pointer to a specific type. For example:

The primary use for void* is for passing pointers to functions that are not allowed to make assumptions about hte type of the object and for returning untyped objects from functions. To use such an object, we must use explicit type conversion.

Functions using void* pointers typically exist at the very lowest level of the system, where real hardware resources are manipulated. For example:

Occurrences of void* at higher levels of the system should be viewed with suspicion because they are likely indicators of design errors. Where used for optimization, void* can be hidden behind a type-safe interface.

Pointers to functions and pointers to members cannot be assigned to void*s.

Structure Pointer Dereference Operator
Structure objects are often accessed through pointers using the -> operator. When P is a pointer, p->m is equivalent to (*p).m.