C Programming: How to Work Pointer Math in an Array - dummies

C Programming: How to Work Pointer Math in an Array

By Dan Gookin

What happens when you increment a pointer in C programming? Say that pointer variable dave references a variable at memory address 0x8000. If so, consider this statement:

dave++;

What would the value of pointer dave be?

Your first inclination might be to say that dave would be incremented by 1, which is correct. But the result of the calculation may not be 0x8001. That’s because the address stored in a pointer variable is incremented by one unit, not by one digit.

What’s a unit?

It depends on the variable type. If pointer dave is a char pointer, indeed the new address could be 0x8001. But if dave were an int or a float, the new address would be the same as

0x8000 + sizeof(int)

or

0x8000 + sizeof(float)

On most systems, an int is 4 bytes, so you could guess that dave would equal 0x8004 after the increment operation. But why guess when you can code?

Arrays and Pointer Math illustrates a simple program, something you could code without using pointers: Fill an int array with values 1 through 10, and then display the array and its values. But in Arrays and Pointer Math, a pointer is used to fill the array.

ARRAYS AND POINTER MATH

#include <stdio.h>
int main()
{
 int numbers[10];
 int x;
 int *pn;
 pn = numbers; /* initialize pointer */
/* Fill array */
 for(x=0;x<10;x++)
 {
 *pn=x+1;
 pn++;
 }
/* Display array */
 for(x=0;x<10;x++)
 printf("numbers[%d] = %dn",
 x+1,numbers[x]);
 return(0);
}

Line 7 declares the pointer pn, and Line 9 initializes it. The & isn’t needed here because numbers is an array, not an individual variable. At that point, the pointer holds the base address of the array. Keep in mind that the array is empty.

image0.jpg

The for loop at Lines 12 through 16 fills the numbers array. The first element is filled at Line 14 using the peeker notation for pointer pn. Then at Line 15, pointer pn is incremented one unit. It now points at the next element in the array, and the loop repeats.

Exercise 1: Copy the source code from Arrays and Pointer Math into your editor. Build and run.

Exercise 2: Modify your source code from Exercise 1 so that the address of each element in the array is displayed along with its value.

In the output of Exercise 2, you should see that each address is separated by 4 bytes (assuming that the size of an int is 4 bytes on your machine). In fact, the addresses probably all end in the hex digits 0, 4, 8, and C.

Exercise 3: Complete the conversion of Arrays and Pointer Math, and what you began in Exercise 2, by having the second for loop display the array’s values using the peeker side of pointer variable pn.

Exercise 4: Create a new project that fills a char array by using pointers similar to the ones shown in Arrays and Pointer Math. Set the char array’s size to 27 so that it can hold 26 letters. Fill the array with the letters ‘A’ through ‘Z’ by using pointer notation. Display the results by using pointer notation.

Here’s a big hint:

*pn=x+'A';

SOLUTION TO EXERCISE 4

#include <stdio.h>
int main()
{
 char alphabet[27];
 int x;
 char *pa;
 pa = alphabet; /* initialize pointer */
/* Fill array */
 for(x=0;x<26;x++)
 {
 *pa=x+'A';
 pa++;
 }
 pa = alphabet;
/* Display array */
 for(x=0;x<26;x++)
 {
 putchar(*pa);
 pa++;
 }
 putchar('n');
 return(0);
}

The source code in Solution to Exercise 4 should be rather lucid, performing each task one step at a time. But keep in mind that many C programmers like to combine statements, and such combinations happen frequently with pointers.

Exercise 5: Combine the two statements in the first for loop from Solution to Exercise 4 to be only one statement:

*pa++=x+'A';

Ensure that you type it in properly. Build and run.

The output is the same. What that ugly mess does is described here:

x+’A’    This part of the statement is executed first, adding the value of variable x to letter A. The net effect is that the code marches up the alphabet as the value of x increases.

*pa    The result of x+’A’ is placed into the memory location specified by pointer pa.

++    The value of variable pa — the memory address — is incremented one unit. Because the ++ appears after the variable, the value is incremented after the value at that address is read.

Keeping the two statements separate still works. But not every programmer does that! Many of them love to stack up pointers with the increment operator. Watch out for it! Or, if you understand it, use it.

Exercise 6: Fix up your source code from Exercise 5 so that the second for loop uses the *pa++ monster.

Hopefully, the *pa++ pointer-thing makes sense. If not, take a nap and then come back and examine Head-Imploding Program.

HEAD-IMPLODING PROGRAM

#include <stdio.h>
int main()
{
 char alpha = 'A';
 int x;
 char *pa;
 pa = &alpha; /* initialize pointer */
 for(x=0;x<26;x++)
 putchar((*pa)++);
 putchar('n');
 return(0);
}

The source code from Listing 19-4 deals with a single char variable and not an array. Therefore, the pointer initialization in Line 9 requires the & prefix. Don’t forget that!

Line 12 in this code contains the booger (*pa)++. It looks similar to *pa++, but it’s definitely not. Unlike *pa++, which peeks at a value and then increments the pointer, the (*pa)++ construction increments a value being peeked at; the pointer is unchanged.

Exercise 7: Edit, build, and run a new program by using the source code from Head-Imploding Program.

The (*pa)++ operation works, thanks to the parentheses. The program fetches the value represented by *pa first and then that value is incremented. The pointer variable, pn, isn’t affected by the operation.

To help avoid confusion on this topic here are the various cryptic pointer/peeker notation doodads:

Expression Address p Value *p
*p++ Incremented after the value is read Unchanged
*(p++) Incremented after the value is read Unchanged
(*p)++ Unchanged Incremented after it’s read
*++p Incremented before the value is read Unchanged
*(++p) Incremented before the value is read Unchanged
++*p Unchanged Incremented before it’s read
++(*p) Unchanged Incremented before it’s read