790 likes | 919 Vues
Working with Pointers. An exercise in destroying your computer. What is this?. Your worst nightmare! Comes from pointer misuse. Let’s look at Memory! Blue is memory address, Black is value. 1 -4717. 2 -901. 3 76. 4 -0. 5 98131. 6 -1038. 7 -554. 8 7462. 9 312. 11 3619. 10
E N D
Working with Pointers An exercise in destroying your computer
What is this? • Your worst nightmare! • Comes from pointer misuse
Let’s look at Memory!Blue is memory address, Black is value 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25 -4717 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Declare an intint myInt; 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt -4717 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
What’ve we done? • By declaring the int, we’ve taken up just enough memory to hold an int • We don’t know where in memory (the address) that it’s located • Computer picks “at random” • What value is at that memory location? • Can we print that value out? • The value –4717 would print! (garbage)
Copy 42 into that Section of MemorymyInt = 42; 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25 myInt 26 -19 27 21511 42 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Pointers • Allow us to get to the address of where information is located • Similar to call forwarding • Ask the pointer where to go • Go there for the information • To create a pointer, we use the * • Follows format of <data type> <name>; • Example: int* ptr;
Declare an int pointerint* ptr; 1 -4717 2 -901 3 76 4 -0 5ptr 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Now what have we done? • Created a new variable of type ptr that points to an int • Notice that we haven’t initialized the pointer to “point” to myInt yet • What if we print the pointer out?
cout << ptr;(prints out value of ptr: 98131) 1 -4717 2 -901 3 76 4 -0 5ptr 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Problem • How do we get address of myInt so ptr can point to it? • Remember, we can still access the value of myInt directly int someInt = myInt; • We really need the pointer to store the address of where myInt is located • We do not need to store the value of myInt for the pointer (just the address)
The & operator • Use the & operator to get the address of where the variable is in memory • What would the following statement print to the screen? cout << &myInt << endl;
What would happen?cout << &myInt; 1 -4717 2 -901 3 76 4 -0 5ptr 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Getting the Pointer to Point • We now need “ptr” to point to myInt • Code: ptr = &myInt; ptr is a pointer, so it expects an address to be assigned to it Here, we get the address of where myInt is stored in memory and copy that value into “ptr”
Before 1 -4717 2 -901 3 76 4 -0 5ptr 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Afterptr = &myInt; 1 -4717 2 -901 3 76 4 -0 5ptr 25 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
What would this do?ptr = myInt; 1 -4717 2 -901 3 76 4 -0 5ptr 98186 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Wrong Addressptr = myInt; 1 -4717 2 -901 3 76 4 -0 5ptr 42 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Tricky Screens of Death! • Last thing to learn is how to “de-reference” a pointer • This means “how to follow the pointer” • Unfortunately, we use the * operator as well • Example: cout << *ptr << endl; Follow wherever ptr is pointing to and print that value out.
Follow the Pointer and Print it Outcout << *ptr << endl; 1 -4717 2 -901 3 76 4 -0 5ptr 25 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25myInt 42 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Another ExampleBlue is memory address, Black is value, Red is variable name 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25 -4717 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Declare a Pointerint *ptr; 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 ptr -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25 -4717 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
What would happen?cout << *ptr << endl; 1 -4717 2 -901 3 76 4 -0 5 98131 6 -1038 7 -554 8 7462 9 312 11 3619 10 ptr -6 12 -4717 13 60981 14 4148 21 -78781 15 86851 16 -5155 17 95151 18 -47 19 2251 20 0 28 -9 22 -901 23 -6 24 6720 25 -4717 26 -19 27 21511 32 9 35 7851 29 17 31 -651 34 -896761 30 -6561 33 761 37 9996 38 674547 39 -6868 40 -1 41 5431 42 -4717 36 -6
Why do I need Pointers? • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 -2 91 571 3 4 5 -2991 0 -33 6 7 8 41 61 -1
Declare myInt • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 -2 91 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Call the function • Because parameter passing only passes a copy so the function can’t change main’s variables! voidcannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 -2 91 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Here’s where the Copy is Made • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 x -2 17 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Changing Only Local Copy • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 x -2 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Print Out Local Copy (6) • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 x -2 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Return to Main (print 17)(x is gone and leaves garbage) • Because parameter passing only passes a copy so the function can’t change main’s variables! void cannotChange (int x) { x = 6; cout << x << endl; } void main ( ) { int myInt = 17; cannotChange (myInt); cout << myInt << endl; } Memory 0 1 2 -2 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Now with Pointers void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 -2 6 571 3 4 5 -2991 0 -33 6 7 8 41 412 -1
Declare myInt void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 -2 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Declare a Pointer to myInt void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 ptr 7 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Pass a Copy of ptr void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 ptr 7 6 571 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Pass a Copy of ptr void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 x ptr 7 6 7 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Change Whatever x is Pointing too void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 x ptr 7 6 7 3 4 5 -2991 0 -33 6 7 8 myInt 41 17 -1
Change Whatever x is Pointing too void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 x ptr 7 6 7 3 4 5 -2991 0 -33 6 7 8 myInt 41 6 -1
Follow x and Print it Out (6) void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 x ptr 7 6 7 3 4 5 -2991 0 -33 6 7 8 myInt 41 6 -1
See the Change in main (6 also) void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; } Memory 0 1 2 x ptr 7 6 7 3 4 5 -2991 0 -33 6 7 8 myInt 41 6 -1
Interesting Note At this point, these two statements print out the same thing! cout << *ptr << endl; cout << myInt << endl So do these! cout << ptr << endl; cout << &myInt << endl; WHY? void canChange (int* x) { *x = 6; cout << *x << endl; } void main ( ) { int myInt = 17; int* ptr = &myInt; canChange (ptr); cout << myInt << endl; }
Summary of Pointers • To understand pointers, you need to understand memory • The & is the secret to it all! • Create and de-reference with * • Passing a pointer to a function can make changes to the main
What the is a Linked List? • A List is a collection of data elements in an array structure. From any given element in the array, the previous and next items can be obtained by moving to adjacent memory locations. • A Linked List is a collection of data elements where the location of each element in memory is only recorded by a pointer from a previous element. The data elements may happen to be adjacent in memory, but you cannot rely on this.
22 101 695 55 27 22 101 695 55 27 What the is a Linked List? • List : (Array of 5 elements : simple integers) • Linked List : (5 elements - all simple integers)
What the is a Linked List? • Are just a sequence of data linked together in memory. • Each element in the list is made up of data plus a pointer to the next element in the list. • Node is the common name used for this data plus the associated pointer to the next item in the list. • However, many kilo-bytes of data : names, addresses, student-ids, etc - could be stored at each Node. • A chain is only as strong as its weakest link. • Similarly, if something erased or corrupted a Node in the middle of the list, then Nodes after this will NOT be found !
Queues : FIFO Vs LIFO • Queues can be of two main types : • FIFO - First In First Out • The first item into the queue is the first to be processed or output. • Example : Supermarket checkout queue. • LIFO queue - Last In First Out. • The last item into the queue is the first one out. • Example : Stack of paper - where you put paper on top of each other and can only get to a page in the stack by removing each page on top of it in turn.
Linked Lists - All are LIFO in this Lecture • We are going to build all Linked Lists in this lecture on a LIFO queue, but we could have made them all FIFO instead. • Exercise : As an exercise that will help you understand queues and Linked Lists, you can convert these examples to FIFO.
Building a Basic Linked List #include <iostream.h> // for cin and cout. #include <mem.h> // for NULL. #include <stdio.h> // getchar // Define the type of data to be stored at each node typedef float ListElement; struct Node { ListElement Value; // Data stored at this Node Node* Next; // Pointer to Next Node in the List };
Basic Linked List - only 4 Functions class Linked_List { private: Node *First; public: Linked_List(); // Constructor // Add Node into the start of a Linked List void Insert_Node (ListElement In_Value); };