410 likes | 577 Views
CSE 20232 Lecture 26 – Pointers. What is a pointer? & and * operators Using a pointer to access array elements Using pointers to implement reference parameters in C New and delete Using pointers to create dynamically sized arrays. L-values and R-values.
E N D
CSE 20232Lecture 26 – Pointers • What is a pointer? • & and * operators • Using a pointer to access array elements • Using pointers to implement reference parameters in C • New and delete • Using pointers to create dynamically sized arrays
L-values and R-values • The l-value of an object is its address • The r-value of an object is its data value • The compiler determines from the C/C++ statement whether to use an object’s l-value or r-value
L-value vs. R-value example int x, y; // anytime a value is to be assigned to an object, // the l-value (address) of that object is needed. // x below is taken to represent the l-value of x x = 3; // anytime the value of an object is needed, // the r-value of that object is used // x below is taken to represent the r-value of x y = x + 3; // notice objects on left of assignments represent // their l-values, and on the right of assignments // represent r-values
What is a pointer? • A pointer is an object that has as its value the address of another object • Or put another way, a pointer is an object that has as its r-value the l-value of some other object • We say the pointer “point to” the other object • Why bother? • Pointers facilitate dynamic memory management • Pointers can be used to create linear and non-linear linked data structures (lists, trees, graphs, …) • Swapping pointer values is often more efficient than moving what they point to in momory
Pointer Related Operators • The & operator is used to explicitly return the l-value of an object • Notice this is slightly different than the use of & in the declaration of reference parameters • The * operator is used to dereference a pointer and return the r-value of the object it points to • Format of pointer declaration • <data_type> *<pointer_name>;
Pointer Example // declare integers int a(3), b, c;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a; // set p to point to a p = &a;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a; // set p to point to a p = &a; // set what p points to to 12 *p = 12;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a; // set p to point to a p = &a; // set what p points to to 12 *p = 12; // set q to point to what p does q = p;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a; // set p to point to a p = &a; // set what p points to to 12 *p = 12; // set q to point to what p does q = p; // move p to next int in memory p++;
Pointer Example // declare integers int a(3), b, c; // declare pointers to integers int * p, *q; // set b to equal a b = a; // set p to point to a p = &a; // set what p points to to 12 *p = 12; // set q to point to what p does q = p; // move p to next int in memory p++; // sum what p & q point to c = *p + *q;
Using pointers to access and array • Basic steps … • Set pointer (p) to point to first element • Use (*p) to set value of the array element that p points to • Advance p to next element (p++) • Note: amount of increment is based on the size of what is pointed to – sizeof(int), etc
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i;
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // pass # 1
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // pass # 2
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // pass # 3
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // pass # 4
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // pass # 5
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]);
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]); // use pointer to scale all // array values for (i=6; i<=10; i++, p++) *p = i * (*p); // pass # 1
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]); // use pointer to scale all // array values for (i=6; i<=10; i++, p++) *p = i * (*p); // pass # 2
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]); // use pointer to scale all // array values for (i=6; i<=10; i++, p++) *p = i * (*p); // pass # 3
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]); // use pointer to scale all // array values for (i=6; i<=10; i++, p++) *p = i * (*p); // pass # 4
Using a pointer to access array elements // declare array of doubles double A[5]; // and declare a loop index I int i; // use loop index to set array // all values to 100 for (i=0; i<5; i++) A[i] = 100.0; // declare pointer to doubles double * p; // set p to point to A[0] p = A; // or p = &(A[0]); // use pointer to scale all // array values for (i=6; i<=10; i++, p++) *p = i * (*p); // pass # 5
Using pointers in C to implement reference parameters • There is no true reference parameter passing mode in C (only in C++) • In C, all function parameters are value parameters • References are passed as pointers and then are dereferenced in the function to change what is pointed to
Example of C vs C++ “Reference” parameters // declaration in C++ // declaration in C // using reference parameters // using pointers void swap (int& a, int& b) void swap (int *a, int *b) { { int temp = a; int temp = *a; a = b; *a = *b; b = temp; *b = temp; } } int main() int main() { { int x=5, y=12; int x=5, y=12; // the call in C++ // the call in C – pass l-values swap (x, y); swap(&x, &y); // now x == 12 & y == 5 // now x == 12 & y == 5 ... ... } }
Swapping or changing values of pointers • In C++ a swap function that swaps pointer values • Uses reference parameters for the two pointers • Assigns one pointer the value of the other • They now point to what the other used to • However, In C a swap function to swap pointer values • Must have parameters that are pointers to pointers • The assignments involve double indirection
Example of C vs C++ Swapping pointer values // declaration in C++ // declaration in C // using reference parameters // using pointers void swap ((int*)& a, (int*)& b) void swap ((int*) *a, (int*) *b) { { int *temp = a; int *temp = **a; a = b; **a = **b; b = temp; **b = *temp; } } int main() int main() { { int x=5, y=12; int x=5, y=12; int *p=&x, *q=&y; int *p=&, *q=&y; // the call in C++ // the call in C – pass l-values swap (p, q); swap(&p, &q); // now p points to y // now p points to y // and q points to x // and q points to x ... ... } }
New • A pointer can be used to point to a dynamically allocated nameless object while the program is running • New() allocates a nameless object from the free memory store (or runtime heap) and returns its address • NULL is a special value for pointers indicating that it points to nothing • New returns NULL if the allocation fails
Delete • Delete is used to return dynamically allocated objects that are no longer needed back to the free memory store • Failure to use delete causes memory leaks • NULL is a special value for pointers indicating that it points to nothing
New and delete example // declare a pointer to an int int *p; // allocate an int for the pointer to point to p = new int; if (NULL != p) // if allocation did not fail { // use the int that p points to cout << “ Enter your age: “; cin >> *p; cout << “Next year you will be “ << *p+1; // when done, free the dynamically allocated memory delete p; }
Dynamically allocated arrays • Maximum array size can be set … • At compile time, using fixed sizes • During run time, with flexible sizes • Use new to allocate int *A = new int[size]; // note [size] • And use delete when done delete [] A; // note required [] for array
Example:Read & alphabetize words • Given a file “randwords.txt” containing • Line 1: n (the number of numbers following) • Next n lines: words • Perform the following steps • Open file • Read number • Allocate array just big enough • Read & insertion sort words • Write words out into file “dictwords.txt” • Delete array
Sample word files File: “randwords.txt” 5 make these words into dictionary File: “dictwords.txt” 5 dictionary into make these words
Dynamically allocated array example (page 1) // read and sort words into dictionary order #include <iostream> #inlclude <fstream> #include <string> using namespace std; int main () { ifstream infile(“randwords.txt”); if (infile.fail()) { cout << “Word file could not be opened”); exit(1); } // next step read size and allocate array
Dynamically allocated array example (page 2) // next step read size and allocate array int num; infile >> num; string *words; words = new string[num]; // exactly the right size if (NULL == words) { cout << “Error allocating space for words”; exit(1); } // next step read and sort input words
Dynamically allocated array example (page 3) // next step read and sort input words for (int n=0; n<num; n++) { string wd; infile >> wd; // get next word from file // now shift all previously read words that follow wd // in the dictionary one position to the right for (int i=n; i>0; i++) { if (words[i-1] < wd) break; // leave loop since this is the place to put wd words[i] = words[i-1]; // shift following word right } words[i] = wd; // put wd in correct place in array } infile.close(); // next step write words to output file
Dynamically allocated array example (page 4) // next step write words to output file ofstream outfile(“dictwords.txt”); if (outfile.fail()) { cout << “Could not open dictionary file”; exit(3); } outfile << num << endl; // write out number of words for (int i=0; i<num; i++) ofstream << words[i] << endl; // write out each word outfile.close(); // done with array so free memory space delete [] words; return 0; }