Jump to content

Pointer arithmetic

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Rohitbd (talk | contribs) at 20:23, 1 July 2005 (Declaration and initialisation). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Pointer arithmetic is a particular arithmetic involving pointers, typical of the C programming language.

In pointer arithmetic, the unit is the size of the pointer's type. For example, adding 1 to a pointer to integer values (which typically span 4 bytes) will increment the pointer by 4. But, the end result will be in the pointer pointing right at the next element, which was probably the intended result.

Pointer arithmetic provides the programmer with a single way of dealing with different types: adding and subtracting the number of elements required instead of the actual offset in bytes. In particular, the C definition explicitly declares that the syntax a[n], which is the n-th element of the array pointed by a, is equivalent to *(a+n), which is the content of the element pointed by a+n.

While powerful, pointer arithmetic can be a source of computer bugs. It tends to confuse programmers, forcing them into different contexts: an expression can be an ordinary arithmetic one or a pointer arithmetic one, and sometimes it is easy to mistake one for the other.

Many modern high level computer languages (for example Java) do not permit direct access to memory using addresses, so concepts of pointers and pointer arithmetic are not relevant. This is deliberate, as many programming tasks do not require specific knowledge of where and how in computer memory data is stored.

Pointer manipulation in C/C++

Shown below are some pointer manipulation techniques common to both C and C++.

Declaration and initialisation

The basic rules to successfully use pointers are the same as those for normal variables:
1) A pointer variable is a "name" given to a memory location, just like any other variable.
2) As any variable, the data that the pointer variable contains is not initialised.
3) The data contained in a pointer variable is interpreted by the run-time as an address. Most important point.

Points 1, 2 and 3 together mean that it is dangerous to use pointer variables without initialising them. For example,

int *p; //Pointer to int datatype.
int x; //Variable of datatype int.

*p = 10; /* Will crash, see point 2 above. The pointer contains garbage data - which evaluates to a random address.
            Attempting to access the memory at that address will in most cases cause a memory access violation. */

p = 0; /* Valid, but cannot be used since "0" is an address and most probably used by the OS. */
*p = 10; /* Will crash due to the above reason. We are trying to write "10" into the memory address "0". */

p = malloc(sizeof(int)); /* For C. Valid, can be used since we are now asking the system to allocate a valid address into p. */
/* OR */
p = new int; /* For C++. Valid, can be used since we are now asking the system to allocate a valid address into p. */
/* OR */
p = &x; /* Both C/C++. Valid, here we are putting the address of x into p. */

*p = 10; /* Will work, since p now contains a valid address. */

printf("%d", *p); //Will work, since p now contains a valid address.

Pointers initialised using the new operator must be reclaimed explicitly, since when the program (or function) terminates, although the pointer variable is destroyed, the memory location (address) that the pointer was pointing to might not be. Memory allocated using the new operator must be reclaimed before the function terminates by using the delete operator.

delete p;

Using pointers

Once a pointer has been initialised, it can be used to perform various operations on the memory block that it points to.

int *p; //Pointer to an int datatype.
int x; //Variable of datatype int.

p = &x; //Initialise the pointer with the address of x.

x = 10;
printf("x = %d", *p);

Prints:
x = 10

*p = 100;
printf("x = %d", x);

Prints:
x = 100

The above shows that x or *p refer to the same memory location and modifying either causes the change to appear in the other. The difference between x and p is that while x literally is the name given to a memory location, p stores the address of that memory location as it's data. Of course, p itself is also bound to be literally the name of another memory location just as x is. Hence,

printf("%d", &x); //Address of x.

Prints:
0xAABBEFF7 (This is the address that x is the name of)

printf("%d", p); //Data contained in p -> the address of x.

Prints:
0xAABBEFF7 (This is the address that p contains, and is the address that x represents)

printf("%d", &p); //Address of p itself.

Prints:
0xFFCC4433 (This is the address that p is the name of)