Pointer Variables
A pointer is a variable that contains a memory address
The address is commonly the location of another variable in memory
This pointer “points” to the other variable in memory
A pointer is declared using the general statement:
type *name; e.g. int *i1;
Important Uses of Pointers
Allows functions to modify their arguments
Supports dynamic memory allocation functions
Improves the efficiency of certain routines
Allows communication to other functions, programs, and hardware using shared memory and memory transfers
Pointers are one of the most powerful features of C/C++ but are also the most dangerous
Pointer Operators
&b return the memory address of variable b
*p return the value of the variable at address p
* is the complement of & so that *(&b)=b
These operators have a higher precedence than other arithmetic operators except urinary minus which is equal
int b = 7777, *p;
p = &b;
cout << *p; 7777
A Variable Pointing to Another Variable
Memory address Variable in memory
1000 1003
1001
1002
1003 7777
1004
p
i1 *p
Pointer Expressions
p = q pointer assignment
p++, p-- increment and decrement
p = p + i addition of an integer i
p = p - i subtraction of an integer i
p == q test for equality
p < q , p > q pointer comparison
char *ch = 3000;int *i = 3000;
expression Memory (bytes)
expression
ch 3000 i
ch + 1 3001
ch + 2 3002
ch + 3 3003
ch + 4 3004 i + 1
ch + 5 3005
Pointers and Arrays
A 1D array is equivalent to a pointer to the first element
There are two ways of accessing arrays:
pointer arithmetic and array indexing, s1[i]=*(s1+i)
Indexing can also be used on pointer variables
char s1[6] = “peach”, *p1;
p1 = s1;
cout << s1[3] << *(p1+3) << p1[3] << *(s1+3); cccc
Passing Pointers and Arrays to Functions
1D arrays and pointers are interchangeable when passing arguments to functions
Since the memory location is passed to the function it will modify the contents of the array: call by reference
No copies of the array are made when passed to the function
Be sure to know the boundaries of the array to avoid invalid memory access
Modifying Function Arguments
Pointers allow C functions to modify their arguments
call by value
int i = 0; fun1(i); cout << i; 0
call by reference
int i = 0; fun2(&i); cout << i; 7777
void fun1(int i) { i = 7777; }
void fun2(int *i) { *i = 7777; }
Array Swapping
int ar[2]={1,2}, br[2]={3,4};
int *a=ar,*b=br,*c;
c = a; a = b; b = c;
cout << a[0] << a[1] << “\n”; 34
cout << b[0] << b[1]; 12
This is more efficient than swapping each element
Make sure you swap any dimension information too
Initializing Pointers
Always initialize your pointers to valid memory locations
A pointer initialized incorrectly is called a wild pointer
Reading data from a wild pointer will return garbage
Writing data to a wild pointer could overwrite program, data or operating system memory, e.g.
int x, *p;
x = 10; *p = x;
Common Problems With Pointers
int x, *p;
x = 10; p = x;
cout << *p; improper usage
char a[10], b[10];
char *p1, *p2;
p1 = a; p2 = b;
if (p1 < p2) …
two arrays will not be stored in any particular order
Dynamic Memory Allocation
static arrays allocate memory at the beginning of program execution
char s1[10], *p1;
p1 = s1;
dynamic memory is allocated during program execution
#include <stdlib.h>
#include <malloc.h>
char *p1;
p1 = (char *)malloc(10*sizeof(char));
Dynamic Arrays
Dynamic arrays are useful because the size of the array can be determined at run-time
The size of the array can be made just small enough for the application
The memory allocated can also be freed for other functions to use when it is no longer needed
It must be freed before the program is finished using the function
free(p1)
New and Delete Operators
C++ provides operators for dynamic memory allocation
p = new type [size]; // new operator for allocation
delete p; // delete operator for freeing memory
int *p1; char *p2;
p1 = new int; p2 = new char [5];
*p1 = 8; strcpy(p2,”ball”);
cout << *p1 << p2;
delete p1; delete p2; 8ball
Comparison with C Allocation Routines
New and delete have the following advantages over malloc and free:
Automatically computes the size needed in bytes
Automatically returns a pointer of a specified type
Provides support for C++ features related to operator overloading, initialization, constructors, and destructors
Note that both malloc and new can take longer to run than static memory allocation for large blocks of memory
Arrays of Pointers
Arrays of pointers can be declared like any other type
char *pa[2];
char p1[]="hello", p2[]="goodbye";
pa[0] = p1; pa[1] = p2;
cout << "\n" << pa[0] << "\t" << pa[1];
cout << "\n" << *(pa[0]+1) << "\t" << *(pa[1]+1);
cout << "\n" << pa[0][1] << "\t" << pa[1][1];
This is useful for developing multidimensional arrays
pa
pa[0]
pa[1]
memory address variable
900 1000
1000 1008
1004 100E
1008 ‘h’
1009 ‘e’
100A ‘l’
100B ‘l’
100C ‘o’
100D ‘\0’
100E ‘g’
100F ‘o’
Pointers to Pointers
Since pointers are stored in memory we can declare pointers to them as well
char **pp;
char *p, s[]="MJ";
p = s; // point to the string
pp = &p; // get the pointer to p
cout << "\n" << p << "\t" << *pp;
cout << "\n" << *(p+1) << "\t" << *(*pp+1);
A pointer to a pointer is the same as an array of pointers
memory address variable
1000 1004
1001
1002
1003
1004 1008
1005
1006
1007
1008 ‘M’
1009 ‘J’
pp
p , s
**pp
*pp
pa
pa[0]
pa[1]
memory address variable
900 1000
1000 1008
1004 100E
1008 ‘h’
1009 ‘e’
100A ‘l’
100B ‘l’
100C ‘o’
100D ‘\0’
100E ‘g’
100F ‘o’
pp
pp[0]
pp[1]
Why Pointers ?
Allows functions to modify their arguments
Supports dynamic memory allocation functions
Improves the efficiency of certain routines (swapping, …)
Allows communication to other functions, programs, and hardware using shared memory and memory transfers
Useful for passing functions to other functions
Important for developing multidimensional dynamic arrays
Key Things to Remember
A 1D array is the same as a pointer to the first element
double s[2] = { 1.0, 2.0 }, *p; p = s;
p[1] == s[1] == *(p+1) == *(s+1) == 2
We can dynamically allocate a 1D array using new
double *p; int n = 10;
p = new double [n]; p[1] = 1.0; delete p;
We can also have a 1D array of pointers which is the same as a pointer to a pointer
double *pa[10], **pp; pp = pa;
More on Static Multidimensional Arrays
2D static arrays are stored in a row by row format
int a[2][3] = {1,2,3,4,5,6}; a =
int *r0, *r1, i;
r0 = a[0]; r1 = a[1];
for(i=0;i<6;i++) cout << r0[i] << “ ”;
1 2 3 4 5 6
for(i=0;i<3;i++) cout << r1[i] << “ ”;
4 5 6
1 2 3
4 5 6
Limitations of Static Multidimensional Arrays
They cannot be passed to general functions since arrays of different sizes cannot be used interchangeably
int a[4][4]; a[0][0] = 1;
f1(a); can’t convert int[4][4] to int[][3]
int fun1(int a[3][3]) { return a[0][0]; }
They also cannot be converted to a pointer to pointer
Only use static multidimensional arrays for simple applications where the size is always fixed
Multidimensional Dynamic Arrays
One way to construct a 2D dynamic array:
First allocate a 1D dynamic array of pointers
This will have a pointer to pointer type
Then initialize each array element to a 1D dynamic array that stores each row done !
Dynamic arrays of any size can be passed to a function since they all have pointer to pointer type
Row Swapping
Rows of a dynamic array can be efficiently swapped by swapping the pointers to the rows
int *pa[2], **m, r0[] = {1,2}, r1[] = {3,4}, *d;
m = pa; m[0] = r0; m[1] = r1;
cout << m[0][0] << m[0][1] << “\n” << m[1][0] << m[1][1];
d = m[0]; m[0] = m[1]; m[1] = d;
cout << “\n\n”;
cout << m[0][0] << m[0][1] << “\n” << m[1][0] << m[1][1];
Pointers to Objects
class string_class {
public:
char str[100];
void strcpy2(char *s);
};
void string_class::strcpy2(char *s) { strcpy(str,s); }
string_class s1, *sp;
s1.strcpy2(“ya”); sp = &s1;
cout << s1.str << (*sp).str << sp->str; yayaya
Arrays of Objects
string_class s1[3], *sp;
s1[0].strcpy2(“one”); s1[1].strcpy2(“two”);
s1[2].strcpy2(“three”); sp = s1;
cout << sp->str << “\n“; sp++; one
cout << sp->str << “\n“; sp++; two
cout << sp->str << “\n”; three
cout << sp[0].str; three
Dynamically Allocated Objects
string_class *sp1,*sp2;
sp1 = new string_class(“apple”); // initialize object to “apple”
sp2 = new string_class [3]; // can’t initialize dynamic arrays
sp2[0].strcpy2(“peach”);
cout << sp1->str << “ “ << sp2[0].str << “\n”;
delete sp1;
delete [3] sp2; // need to put [size] first for dyn object arrays
string_class::string_class(char *s) {
strcpy(str,s); cout << “construct\n”; } // for sp1
string_class::string_class() { cout << “c0\n”; } // for sp2