380 likes | 538 Views
Pointers. c. ‘y’. 0019. i. 2. 0020. name memory address. c. ‘y’. 0019. i. 2. 0020. ptr. 0020. What is pointer. name memory address. Everything stored in a computer program has a memory address. This is especially true of variables. char c=‘y’; int i=2;
E N D
c ‘y’ 0019 i 2 0020 name memory address c ‘y’ 0019 i 2 0020 ptr 0020 What is pointer name memory address • Everything stored in a computer program has a memory address. This is especially true of variables. char c=‘y’; int i=2; • According to the information to the right, the address of variable i is 0020 • The memory address can be used to reference a variable, • addresses can be stored in a variable of a special type called a pointer (variable) • The variable ptr as shown on the right is a pointer variable to the int variable i • So, a pointer is just a reference to something; it’s content is an address;
Declaring a Pointer • A Pointer variable is declared as follows: data_type *pointer_name; • Examples: double *p; int *ptr; int* q; Be careful, int* x, y; declares x as a pointer to an integer while y is just a regular int. • Note the memory/storage associated with what ptr is pointing to is NOT allocated/created just by the defining of ptr, i.e., int *ptr; this does not allocate any memory for ptr to point to • A variable can be a pointer to any data type including another pointer: char **p; or even char ***p; • An example that we have already used for a pointer to a pointer is when talking about command line arguments --- arguments to the main program is : char *argv[];
Declaring a Pointer • Used in conjunction with the concept of a pointer is the address operator: & • The address operator when applied returns the memory address of its operand. • Example: int *p; int x=7; p = &x; • Another operator used in conjunction with the concept of a pointer dereferencing operator: * • The dereferencing operator returns the contents of the memory referenced by the operand. • Example with the above assignment of p=&x; then cout << *p; would print the value 7
c ‘y’ 0019 x 2 0020 Finding the address of a memory location/variable name memory address • The address of a variable can be found by using the address operator & • For example, if one has char c; int x; int *p; Then cout << &c << endl; // will print 19 while cout << &x << endl; // will print 20 cout << p << endl; // on most systems prints 0 cout << *p << endl; // will cause an error When printing p, if p has the value of 0, then *p is generally a reference to memory outside the bounds of the program.
c ‘y’ 0019 x 14 0020 0020 p Finding the address of a memory location/variable name memory address • If one initializes p to a value such as p = &x; Then cout << p << endl; // produces 20 cout << *p << endl; // produces 14 cout << x << endl; // produces 14 • The use of * in the above is a dereferencing of p, i.e, * used in the context is a dereferencing operator.
c ‘y’ 0019 x 47 0020 0020 p Dereferencing a location/variable name memory address • If one initializes p to a value such as p = &x; Then *p is a reference to the x • If we, p = &x; *p = 47; Then cout << p << endl; // produces 20 cout << *p << endl; // produces 47 cout << x << endl; // produces 47
Pointer Constants 000000 000001 004000 To 004003 0 0 1 0 x p 0 0 4 0 1048573 1048574 1048575 Don’t be confused by pointers… int x; int *p; x = 10; P = &x; Pointer variable, p • does not hold the value of x • Its value is an address • pointsto the memory location of x • is a variable itself • has its own memory location (1002300) 1002300
Using pointers • note that star (*) at declaration is not a dereference operator - it just signifies that the variable is a pointer. • A pointer can be assigned a value at declaration int x; int *ip=&x; • multiple pointer variables can point to the same variable int a; int *p, *q, *r; P = q = r = &a;
Multiple Pointers to One Variable int a, *p, *q, *r; p = &a; q = &a; r = q;
Using pointers What does this piece of code do? DRAW a picture!!! int *p1, *p2, one=1, two=2; p1 = &one; p2 = p1; *p1 = *p1 + 1; p1 = &two; *p1 -= 1; cout << *p2 << “ “ << *p1 << endl;
Bad Pointers • A pointer that is not initialized holds an arbitrary value. Hence any reference via the pointer may cause a run time error. This is referred to as a dangling reference. • Assigning a value to the location where an uninitialized pointer points to can lead to unpredictable results: int *ptr; *ptr = 5; // ERROR – dangling reference • NULL is a constant that is assigned to a pointer that does not have a value int *ptr = NULL; //this assigns ptr not *ptr • assigning NULL to pointer does not eliminate the dangling reference problem but it is a convenient constant to compare to int *ptr = NULL, x=5; // ERROR *ptr2 = 5; if (ptr == NULL) ptr = &x; cout << *ptr; // prints 5
x 107 0016 14 0020 71 0024 0016 p Array names and constant pointers • Array name is in fact a constant pointer • A constant pointer is a pointer object where we cannot change the location to which the pointer points • We can however change the value pointed to by the pointer • Confused? • Example int *p; // this is a pointer int x[3]; // this is an array p = x; // p references first // element of an array *p = 112; // changes the 107 to 112 p = p + 1; // assigns 20 to p *p = 102; // changes the 14 to 102 x = p; // is illegal, you cannot change the address of an array. Array names are constants. name memory address
Array names are constant • an array name can be used as name and as a (constant) pointer: x[2]=22; // as name *x=22; // as pointer • a pointer can also be used similarly p[2]=44; // as name *(p+2)=10; // as pointer • since array name is a constant pointer - it’s modification is not legal x = p; // ERROR! P = x; // Is legal and ok
Pointers and Arrays • For an array declared in the following way: int x[200]; • The array’s name becomes a pointer to its 1st element except when the array name is used as an operand to sizeof • That is: • x is the same as &x[0] • *x == x[0] • More generally: • x + i == &x[i] • *(x + i) == x[i]
Pointer Arithmetic • Addition and subtraction of pointers is ok • Pointer + number • Pointer - Pointer • Can be used to traverse through memory • A substitute for array subscript notation.
Pointer Addition • Adds an integer to a pointer • Moves the pointer • Forward (if positive), backward (if negative) • Moves in memory by that many objects • Not bytes! • I.e., p+n increases address by n*sizeof(*p) • Must only be used within an array! • Except you may move one past the end • But you must not dereference there!
Pointer Subtraction • Yields number of objects between the two objects pointed to. • Result can be negative. • Special type to hold result …usually a typedef for long.
Pointer Arithmetic • Given a pointer p, p+n refers to the element that is offset from p by n positions.
c c+1 c+2 Pointer Arithmetic & Different Data Types • address = pointer + (offset * size of element)
Pointer Arithmetic Example /* arith.cpp: Illustrates pointer arithmetic */ #include <iostream> using namespace std; int main(){ float a[] = {1.0, 2.0, 3.0}; cout << "sizeof(float) == " << sizeof(float) << endl; // Increment a pointer: float* p = &a[0]; // or just a; cout << "p == " << p << ", *p == " << *p << endl; ++p; cout << "p == " << p << ", *p == " << *p << endl; // Subtract two pointers: float* diff = (p+1) - p; cout << "diff == " << diff << endl; diff = (char *)(p+1) - (char *)p; cout << "diff == " << diff << endl; } /* Output: sizeof(float) == 4 p == 0012ff80, *p == 1 p == 0012ff84, *p == 2 diff == 1 diff == 4 */
Dereferencing Array Pointers *(a+n) is identical to a[n]
Multi-dimensional Arrays • Muti-dimensional arrays are actually arrays of arrays • int a[2][3]; • a is an array of 2 elements • Each of the two elements is an array of 3 integers • What is sizeof(a[0])? 12, assuming 32-bit integers Draw picture….
Pointer to 2-Dimensional Arrays table[i][j] What is **table?
Pointers to objects • Pointers can point to objects: class MyClass{ public: void setD(int i){d=i;}; int getD() const {return d;}; private: int d; }; MyClass object, *objptr=&object; • members can be accessed using pointers: (*objptr).setD(5); • parentheses around (*objptr) are needed because the dot-operator has a higher priority than the dereferencing operator • a shorthand -> is used for accessing members of the object the pointer points to: cout << objptr->getD();
Exercise 1 • What is the outputof the following program ? Memory address: 1020 1024 1028 … 100 … … … … a int a = 100; int *b = &a; cout << a; cout << &a; cout << b; cout << *b; cout << &b;
Exercise 2 • What is the output of the following program ? int a = 100, b = 88, c = 8; int *p1 = &a, *p2, *p3 = &c; p2 = &b; // p2 points to b p2 = p1; // p2 points to a b = *p3; //assign c to b *p2 = *p3; //assign c to a cout << a << b << c;
Exercise 3 What is the output of the following program ? 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;
Generic Pointers • void* • Allows holding a pointer to any type • Can store any pointer in a void* • Must explicitly cast back to original type to use it • Used often as function parameters • Useful for: • Treating any object as a sequence of bytes • Implementing generic containers
Pointer Indirection (Pointers to Pointers) What is a? &a? *a? p? &p? *p? **p? q? &q? *q? **q? 58
Pointers Indirection 58 • How to access a from p? *p • How to access a from q? **q • How to access a from r? ***r
Array of Pointers & Pointer to Array int *aryOfPtrs[5]; // array of 5 pointers to integer int table [5]; int * ptrToAry = table;
Lvalue vs Rvalue • A C++ expression is either an rvalue or lvalue. • An rvalue expression appears at the right of an assignment. It refers to a value that is to be assigned to a memory cell, i.e. can be used to supply a value for further use, e.g. examine or copy the value. • Examples: x= 5; y= a+2; z=a*6; x=a[2]+3; i=i++; • A lvalue expression appears at the left of an assignment. It identifies a memory cell that is going to receive an rvalue, i.e. the memory cell is being modified. • Example: a = … a[5] = … (a) = … *p = …
Exercise 4 • Given the following lines of codes, int ival = 1024; int ival2 = 2048; int* pi1 = &ival; int* pi2 = &ival2; int** pi3 = 0; • Are the following statements legal or illegal? • (1) pi2 = *pi1; • (2) ival = pi1; • (3) pi3 = &pi2;
Exercise 5: what is wrong? int a = 58; int *p = &a; int **q = &p; int ***r = &q; int ****s = &r; q = &a; s = &q;
Exercise 5: what is the output? #include <iostream> using namespace std; int main(){ int a[5] = {2,4,6,8,22}; int *p = &a[1]; cout << a[0] << " " << p[-1]; cout << a[1] << " " << p[0]; cout << a[2] << *(p+2); cout << (a[4] = = *(p+3)); return 0; }