Pointers & Arrays

An array is a variable that contains N values of the same data type.

 

A variable contains just one value of a specified data type. Declaring a variable is the act of giving a name to the address where the value of the specified data type will be stored.

 

i.e. int myVar ; //declares an integer called myVar. This allocates address space for an int, which we can refer to by its name, myVar

 

The address of myVar can be seen using the ampersand address of operator &myVar, which display a hex address 0x123456

 

Arrays are sized either upon declaration or definition: int myArr[5] ; or int myArr[] = {9,8,7,6,5} ; in the latter case, the compiler automatically sizes the array for the defined values.

 

The compiler allocates contiguous storage for the named array according to the specified data type, multiplied by the number of elements. e.g. an int array with 5 elements would be allocated 4 (number of bytes for an int) x 5 (elements) = 20 bytes = 20 (8bit) address spaces.

 

So, declaring an array gives a name to the first allocated address. If we were to display the array name on its own, we would see the address of the first element in the array.

 

e.g. cout << myArr ; //would display the address of the first element of the array called myArr, as would cout << &myArr ; and cout << &myArr[0] ;

 

Thus myArr, &myArr and &myArr[0] are equivalent, and contain the address of the first element of the array!

 

Since the compiler knows the data type units (i.e. the amount of storage required for the specified data type), arithmetic is carried out upon the name of the array in units of the decalred data type. e.g. an int array has four bytes per element, thus adding 2 to the array identifier name tells the compiler to add 2 address units (as per the data type) which would allow access to the third element of the array

 

e.g. following on from the array defined above, myArr+2 is the address of the third element

 

Since we now know that the name of the array contains the address of the first element of the array, we can declare a pointer of the same data type and assign it with that array address:

 

int *myPtr = myArr ; //which is the same as *myPtr = &myArr

 

myPtr now contains the address of myArr, and can be dereferenced as per normal pointer operations:

 

cout << *myPtr ; //displays the value of the first element in the array

 

It now makes sense that we can perform simple arithmetic operations (e.g. increment/decrement) upon the pointer, to access the desired element within the array.

 

e.g. myPtr+2

 

However, it must be remembered that this is incrementing the address, which now equates to the 3rd address within the array.

 

To obtain the value within that address, it must be dereferenced, taking care of operator precedence!

 

Important! * comes before + in terms of operator precedence, and therefore to access the value in the third element of the array, the dereferencing must be applied to the incremented address (normally carried out within parentheses).

 

e.g. *(myPtr+2)

 

If we were to dereference directly against the addition expression, like so: *myPtr+2 this would firstly dereference myPtr (which has a value of 9) and then add 2 to it, giving an equated value of 11.

 

But since we actually want the third element in the array, we apply the addition expression within parentheses like so: (myPtr+2), and then dereference that, giving: *(myPtr+2) which has a value of 7.
e.g. cout << *(myPtr+2) ; //to access the value in the 3rd element

 

A for loop is commonly used to iterate through the values in an array

 

#include <iostream>
using namespace std;

int main () {

	int myArr[] = {9,8,7,6,5} ;

	cout << "Contents of myArr: \t" << myArr << endl ;
	cout << "Contents of &myArr: \t" << &myArr << endl ;
	cout << "Contents of &myArr[0]: \t" << &myArr[0] << endl ;

	cout << "The value of the third element using array subscript is: " << myArr[2] << endl ;

	int *myPtr = myArr ;

	cout << "The value of the third element using pointer arithmetic is: " << *(myPtr+2) << endl ;
	cout << "The value of the third element using pointer arithmetic is: " << *(myArr+2) << endl ;

	for (int i = 0 ; i < sizeof(myArr)/4 ; i++){

		cout << "Element [" << i << "] at address " << myArr+i << ", contains " << *(myPtr+i) << endl ;
	}

	return 0;
}

Compile & Run:

Contents of myArr:     0x28fee4
Contents of &myArr:    0x28fee4
Contents of &myArr[0]: 0x28fee4
The value of the third element using array subscript is: 7
The value of the third element using pointer arithmetic is: 7 

The value of the third element using pointer arithmetic is: 7
Element [0] at address 0x28fee4, contains 9
Element [1] at address 0x28fee8, contains 8
Element [2] at address 0x28feec, contains 7
Element [3] at address 0x28fef0, contains 6
Element [4] at address 0x28fef4, contains 5

 

 

*Note: On line 17, the array can also be dereferenced directly (using myArr), without the need for a separate pointer as per line 16 (using myPtr) - note the subtle difference!

 

Another simple example:

#include <iostream>
#include <string>
using namespace std;

int main() {
	int myArray[9] = {0}; //array initialisation to 0

	myArray[4] = 7 ; //set 5th element to 4

	*myArray = 42 ;  //set first element to 42

	*(myArray + 2) = 6 ;  //adding 2 int address spaces to go to 3rd element address of array
							//which is then dereferenced to get the value at that address

	for (int i = 0; i < 9 ; i++){
		cout << "myArray element" << i << " contains: " << myArray[i] << endl ;
	}

	return 0;
}

Compile & Run:

myArray element0 contains: 42
myArray element1 contains: 0
myArray element2 contains: 6
myArray element3 contains: 0
myArray element4 contains: 7
myArray element5 contains: 0
myArray element6 contains: 0
myArray element7 contains: 0
myArray element8 contains: 0

Leave a Reply