Pointers Why pointers lowlevel but efficient manipulation of

Pointers

Why pointers? - low-level, but efficient manipulation of memory - dynamic objects § Objects whose memory is allocated during program execution. (Dynamic objects can survive after the function ends in which they were allocated). § Dynamic objects allow flexible-sized arrays and lists

Pointers § A pointer is a variable used for storing the address of a memory cell. § We can use the pointer to reference this memory cell, so to ‘manipulate’ it! n Memory address: Object whose value represents the location (memory address) of another object 1020 … … int a; int* p; Integer a 1024 100 … 10032 1024 … Pointer p

Getting an address: address operator & int a=100; “&a” “the address of a” Memory address: 1020 … … 1024 100 a int a = 100; cout << a; Cout << &a; 100 1024 … … …

Define a pointer type variable: T* Each type of object (variable) has a pointer type, therefore a pointer variable of that type. Type. Name* variablename; int* p; equivalent Type. Name *variablename; int *p; Examples of (uninitialized) pointers int* ip; char* s; int *ip; char *s; // ip is a pointer to an int // s is a pointer to a char

Store the address in a pointer variable Memory address: … 1020 88 1024 100 a int a = 100; int* p = &a; cout << a << " " << &a <<endl; 10032 … 1024 … p Result is: 100 1024 § The value of pointer p is the address of variable a cout << p << " " << &p <<endl; 1024 10032 § A pointer is also a variable, so it has its own memory address p is pointing to a

Dereferencing Operator * § We can access to the value stored in the variable pointed to by preceding the pointer with the “star” operator (*), Memory address: … 1020 88 1024 10032 … 1024 a int a = 100; int* p = &a; cout << a << endl; cout << &a << endl; cout << p << " " << *p << endl; cout << &p << endl; … p *p gives 100

An asterisk (‘*’) has two usages § In a definition, an asterisk indicates that the object is a pointer. char* s; // s is of type pointer to char (char *s; is possible) § In expressions, an asterisk before a pointer indicates the object the pointer pointed to, called dereferencing int i = 1, j; int* ptr; // ptr is an int pointer ptr = &i; // ptr points to i j = *ptr + 1; // j is assigned 2 cout << *ptr << j << endl; // display "12"

Summary on two operators * and & * has two usages: - pointer - dereferencing & has two usages: - getting address - reference (‘call by ref’, see later)

Null Address § 0 is a pointer constant that represents empty or null address the § Indicates that pointer is not pointing to storage of a valid object § Cannot dereference a pointer whose value is null int* ptr; ptr = 0; cout << *ptr << endl; // invalid, ptr // does not point to // a valid int

Example #include <iostream> using namespace std; Result: int main (){ Value 1 is 10 int value 1 = 5, value 2 = 15; Value 2 is 20 int* p 1; int* p 2; p 1 = &value 1; // p 1 = address of value 1 p 2 = &value 2; // p 2 = address of value 2 *p 1 = 10; // value pointed to by p 1=10 *p 2 = *p 1; // value pointed to by p 2= value // pointed to by p 1 = p 2; // p 1 = p 2 (pointer value copied) *p 1 = 20; // value pointed to by p 1 = 20 cout << "value 1==" << value 1 << "/ value 2==" << value 2; return 0; }

Another Pointer Example int a = 3; char s = ‘z’; double d = 1. 03; int* pa = &a; char* ps = &s; double* pd = &d; cout << sizeof(pa) << sizeof(*pa) << sizeof(&pa) << endl; cout << sizeof(ps) << sizeof(*ps) << sizeof(&ps) << endl; cout << sizeof(pd) << sizeof(*pd) << sizeof(&pd) << endl;

Writing pointer type properly Recommended: in C++ … int* a; ? int* b; int *a, *b; int* a, b; a, b are both integer pointers a is integer pointer, b is just integer! typedef int My. Int; My. Int k; typedef int* Int. Pt; Int. Pt a, b; int k;

Traditional Pointer Usage void swap(char* ptr 1, char* ptr 2){ char temp = *ptr 1; *ptr 1 = *ptr 2; *ptr 2 = temp; } int main() { char a = 'y'; char b = 'n'; swap(&a, &b); cout << a << b << endl; return 0; } Use pass-by-value of pointers to ‘change’ variable values C language does not have ‘call by reference’, only ‘call by value’!

Reference: T& void f(int& b) {}; int& b a; l b is an alternative name for a l int main() { int a; f(a); }

Pass by reference (better than ‘pointers’) void swap(char& y, char& z) { char temp = y; y = z; z = temp; } int main() { char a = 'y'; char b = 'n'; swap(a, b); cout << a << b << endl; return 0; } y, z are ‘references’, only names, not like ptr 1, ptr 2 that are variables

Pointer to ‘Struct’ struct Date {…}; Date d={1, 10, 2009}; Date* pd = &d; (*pd). day=2; (*pd). month=11; Or pd->day=2; pd->month=11;

Pointers and arrays

Arrays are pointers! The name of an array points only to the first element not the whole array. 1000 1004 1008 1012 1016

Array name is a pointer constant #include <iostream> Using namespace std; void main (){ // Demonstrate array name is a pointer constant int a[5]; cout << "Address of a[0]: " << &a[0] << endl << "Name as pointer: " << a << endl; } /* result: Address of a[0]: 0 x 0065 FDE 4 Name as pointer: 0 x 0065 FDE 4 */
![Dereference of an array name a[0] 2 a[1] 4 a[2] 6 a[3] 8 a[4] Dereference of an array name a[0] 2 a[1] 4 a[2] 6 a[3] 8 a[4]](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-21.jpg)
Dereference of an array name a[0] 2 a[1] 4 a[2] 6 a[3] 8 a[4] 22 #include <iostream> Using namespace std; void main(){ int a[5] = {2, 4, 6, 8, 22}; cout << *a << " " << a[0] << " " << *(&a[0]); . . . " } //main This element is called a[0] or *a Result is: 2 2 2

Array name as pointer To access an array, any pointer to the first element can be used instead of the name of the array. a p a[0] a[1] a[2] a[3] a[4] 2 4 6 8 22 a We could replace *p by *a #include <iostream> Using namespace std; void main(){ int a[5] = {2, 4, 6, 8, 22}; int* p = a; int i = 0; 2 cout << a[i] << " " << *p; 2. . . }
![Multiple Array Pointers Both a and p are pointers to the same array. A[0] Multiple Array Pointers Both a and p are pointers to the same array. A[0]](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-23.jpg)
Multiple Array Pointers Both a and p are pointers to the same array. A[0] a[0] 2 a[1] 4 a[2] 6 a[3] a[4] 8 22 p P[0] 22 44 #include <iostream> Using namespace std; void main(){ int a[5] = {2, 4, 6, 8, 22} int* p = &a[1]; cout << a[0] << " " << p[-1]; cout << a[1] << " " << p[0]; . . . }

Pointer Arithmetic Given a pointer p, p+n refers to the element that is offset from p by n positions. a 2 p - 1 a + 1 4 p a + 2 6 p + 1 a + 3 8 p + 2 a + 4 22 p + 3
![Dereferencing Array Pointers a[0] a[1] a[2] a[3] a[4] or *(a + 0) or or Dereferencing Array Pointers a[0] a[1] a[2] a[3] a[4] or *(a + 0) or or](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-25.jpg)
Dereferencing Array Pointers a[0] a[1] a[2] a[3] a[4] or *(a + 0) or or *(a *(a + + 1) 2) 3) 4) 2 4 6 8 22 *(a+n) is identical to a[n] a a a + + 1 2 3 4

Summary * two usages: - pointer type definition: - dereferencing: int a; int* p; *p is an integer variable if p = &a; & two usages: - getting address: p = &a; - reference: int& b a; b is an alternative name for a First application in passing parameters (‘swap’ example) int a=10; int b=100; int* p; int* q; p=&a; q=&b; p = q; ? *p = *q; ?
![Two ways of manipulating an array a[n]: like a vector, an array a+n *(a+n): Two ways of manipulating an array a[n]: like a vector, an array a+n *(a+n):](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-27.jpg)
Two ways of manipulating an array a[n]: like a vector, an array a+n *(a+n): like a ‘sequence’ or a ‘list’ ‘a’ points to the first element

Dynamic Objects

Memory Management § Static Memory Allocation § Memory is allocated at compiling time § Dynamic Memory § Memory is allocated at running time { int a[200]; … { int n; cin >> n; a[n]? ? ? } }

Static vs. Dynamic Objects § Static object § Memory is acquired automatically § Memory is returned automatically when object goes out of scope § Dynamic object § Memory is acquired by program with an allocation request § new operation § Dynamic objects can exist beyond the function in which they were allocated § Object memory is returned by a deallocation request § delete operation

Creating a variable (object): new T Syntax ptr = new Some. Type; where ptr is a pointer of type Some. Type Example int* p = new int; Uninitialized int variable p ‘new’ does two things: 1. Create a variable of given type 2. Point the pointer p to the variable

Destructing a variable (object): delete p Syntax delete p; storage pointed to by p is returned to free store and p is now undefined Example p int* p = new int; *p = 10; delete p; 10 ‘delete’ does two things: 1. Return the pointed object to the system 2. Point the pointer p to NULL
![Dynamic Arrays (a collection of variables) p = new T[size]; delete[] p; § Syntax Dynamic Arrays (a collection of variables) p = new T[size]; delete[] p; § Syntax](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-33.jpg)
Dynamic Arrays (a collection of variables) p = new T[size]; delete[] p; § Syntax for allocation: p = new Some. Type[Expression]; § Where § p is a pointer of type Some. Type § Expression is the number of objects to be constructed -- we are making an array § Syntax for de-allocation: delete[] p; § Because of the flexible pointer syntax, p can be considered to be an array

Example Dynamic Memory Allocation § Request for “unnamed” memory from the Operating System int* p, n=10; p = new int; p = new int[100]; p = new int[n]; p p p

Freeing (or deleting) Memory

Allocation Example Need an array of unknown size main() { int n; cout << “How many students? “; cin >> n; int grades[n]; int* grades = new int[n]; for(int i=0; i < n; i++){ int mark; cout << “Input Grade for Student” << (i+1) cin >> mark; grades[i] = mark; } << “ ? : ”; . . . print. Mean( grades, n ); // call a function with dynamic array. . .
![Dangling Pointer Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] = Dangling Pointer Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] =](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-37.jpg)
Dangling Pointer Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] = i; int* B = A; delete[] A; B[0] = 1; // illegal!
![Memory Leak Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] = Memory Leak Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] =](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-38.jpg)
Memory Leak Problem int* A = new int[5]; for(int i=0; i<5; i++) A[i] = i; A A = new int[5]; 0 1 l 22 3 4

Summary Static variables (objects) Dynamic variables (objects) A (direct) named memory location A static part (pointer) + (indirect) nameless memory location (dynamic part) int a; int* pa; a = 20; pa = new int; *pa = 20; a 20 static 20 pa static dynamic

Dynamic array Simple dynamic variable int* p = new int; *p = 10; delete p; p 10 ‘delete’ two actions: 1. Return the object pointed to 2. Point the pointer p to NULL int* p = new int[100]; for (i=1; i<100, i++) p[i] = 10; delete[] p; p 10 10 10 ‘delete p’ is not sufficient for an array!!!

Good practice § Logically, Initialize a pointer with NULL § Always check a pointer before usage § if (p != NULL) *p
![Bad examples { int n; cin >> n; a[n]? ? ? } It’s possible, Bad examples { int n; cin >> n; a[n]? ? ? } It’s possible,](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-42.jpg)
Bad examples { int n; cin >> n; a[n]? ? ? } It’s possible, but not standard, Do: int* a = new int[n]; n=100; int* p = new int[n]; N=150; P[130]? ? ? No! the array stays with the size 100.

More pointers

Pointers to pointers

Pointer to pointer: T** int a; int* p; int** q; a = 58; p = &a; q = &p; 58 a p q a, *p, and **q are the same object whose value is 58! But q = &a is illegal!

Pointer to pointers and 2 D arrays
![Pointer of pointers & 2 D Arrays What is **table ? table[i][j] table[0] or Pointer of pointers & 2 D Arrays What is **table ? table[i][j] table[0] or](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-47.jpg)
Pointer of pointers & 2 D Arrays What is **table ? table[i][j] table[0] or *( table + 0 ) table + 1 table[1] or *( table + 1 ) table + 2 table[2] or *( table + 2 ) int table[3][4]; for(int i=0; i<3; i++){ for(int j=0; j<4; j++) cout << *(*(table+i) +j); cout << endl; }
![table and table[0] are of the same address int table[2][2] = {{0, 1}, {2, table and table[0] are of the same address int table[2][2] = {{0, 1}, {2,](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-48.jpg)
table and table[0] are of the same address int table[2][2] = {{0, 1}, {2, 3}}; cout << table << endl; cout << *table << endl; //same as above cout << table[0] << endl; // same as above 0 xffbff 938 cout << *table[0] << endl; cout << table[0][0] << endl; // same as above cout << **table << end; // same as above 0 0 0

Array of Pointers & Pointer to Array p a b c An array of Pointers int a = 1, b = 2, c = 3; int* p[5]; p[0] = &a; p[1] = &b; p[2] = &c; A pointer to an array int list[5] = {9, 8, 7, 6, 5}; int* p; p = list; //points to 1 st entry p = &list[0]; //points to 1 st entry p = &list[1]; //points to 2 nd entry p = list + 1; //points to 2 nd entry

A Dynamic Table * A dynamic table is an array of pointers to save space when not all rows of the array are full. int** table; table = new int*[6]; table[0] table[1] table[2] table[3] table[4] table[5] = = = new int[4]; new int[7]; new int[1]; new int[3]; new int[2]; NULL; table[0] table[1] table[2] table[3] table[4] table[5]
![table[0] table[1] table[2] table[3] table[4] table[5] 32 18 12 24 13 11 16 12 table[0] table[1] table[2] table[3] table[4] table[5] 32 18 12 24 13 11 16 12](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-51.jpg)
table[0] table[1] table[2] table[3] table[4] table[5] 32 18 12 24 13 11 16 12 42 19 14 22 13 13 14 11 18 table[0][0] = 32; table[0][1] = 18; … *(*(table+i)+j) is table[i][j]

Create a matrix of any dimensions, m by n: Ideas: int m, n; cin >> m >> n >> endl; int** mat; mat = new int*[m]; for (int i=0; i<m; i++) mat[i] = new int[n]; Put it into a function: int main() { int m, n; cin >> m >> n >> endl; int** matrix; matrix = imatrix(m, n); … } int** imatrix(int m, int n) { int** mat; mat = new int*[m]; for (int i=0; i<n; i++) mat[i] = new int[n]; return mat; }
![Dynamic matrix deallocation for(int i=0; i<6; i++) delete[] mat[i]; delete[] mat; void delete. Imatrix(int** Dynamic matrix deallocation for(int i=0; i<6; i++) delete[] mat[i]; delete[] mat; void delete. Imatrix(int**](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-53.jpg)
Dynamic matrix deallocation for(int i=0; i<6; i++) delete[] mat[i]; delete[] mat; void delete. Imatrix(int** mat, int m, int n) { for(int i=0; i<m; i++) delete[] mat[i]; delete[] mat; } § Each row must be deleted individually § Be careful to delete each row before deleting the table pointer.
![Examples: main() arguments int main() int main(int argc, char* argv[]) E. g. a. out Examples: main() arguments int main() int main(int argc, char* argv[]) E. g. a. out](http://slidetodoc.com/presentation_image/066c736875b5af3124dbf65bc5788bda/image-54.jpg)
Examples: main() arguments int main() int main(int argc, char* argv[]) E. g. a. out 20 30 int main(int argc, char* argv[]) { if (argc != 3) { troubles!!!} int rows = atoi(argv[1]); int col = atoi(argv[2]); } § ‘argc’ is the actual number of arguments § ‘argv’ is an array of char*, each pointing to a character

Constantness: object or pointer?

(const) object (*const) pointer § ‘const’ only modifies a type § const T* p constant T, so constant object, const *p § ‘const’ only modifies a type as it might be one of them: § const T* p § const T *p § T *const p constant pointer § const T *const p = constant pointer to constant object (both pointer AND object are constants!) § No ‘const*’ operator.

Example: A constant object with ‘const’: const int* p; A constant pointer with ‘*const’: int *const p; A constant object AND pointer is: const int *const p; 57

‘const object’ and ‘constant pointer’ § Pointer to const object: the content is const, pointer is free § § int x=10, y=20; const int* pc = &x; pc = &y // OK *pc = 5; // wrong! int const *pc § Const pointer: the pointer is const, content is free § § int x=10, y=20; Int *const cp = &x; *cp = 5; // OK cp = &y; // wrong!

Because of ambiguous ‘const int** b’ and ‘const int **b’, so it is ‘const int’! int main(){ int** iptr; int i, j; void f 1(const int** bar){ bar[1][1] = 5; bar[1] = new int[3]; Bad: const int ** bar iptr = new int*[10]; for( i = 0; i < 10; i++ ) iptr[i] = new int[10]; for( i = 0; i < 10; i++ ) for( j = 0; i < 10; i++ // wrong: change int // ok } ) void f 2(int *const *bar){ bar[1][1] = 5; bar[1] = new int[3]; bar = new int*[3]; iptr[i][j] = i*j; Bad: int * const * bar // ok // wrong: change int* // ok f 1(iptr); f 2(iptr); f 3(iptr); } } void f 3(int **const bar) { bar[1][1] = 5; // ok bar[1]= new int[3]; // ok bar = new int*[3]; // wrong: change int** } Writing properly matters!!! 59

More examples … int main(){ int i = 3, j = 10; int* ip = &i; *ip = 4; const int* ipc = ip; *ip = 5; // *ipc is now 5 ip = &j; int *const *ipp 1 = &ip; const int* const *ipp 2 = &ip; // ok const int** ipp 3 = &ipc; // ok ipp 3 = &ip; // wrong: changing ipp 3 // indirectly/inadvertently changes **ipp // wrong: same reason as above, because if allowed ipp 4 //could be changed later const int** ipp 4 = &ip; return 0; } 60
- Slides: 60