450 likes | 547 Views
DCT1063 Programming 2 CHAPTER 1 POINTERS. Mohd Nazri Bin Ibrahim Faculty of Computer, Media & Technology TATi University College nazri@tatiuc.edu.my. Pointer. After completing this chapter student should be able to:-. What Are Pointers?.
E N D
DCT1063 Programming 2 CHAPTER 1 POINTERS Mohd Nazri Bin Ibrahim Faculty of Computer, Media & Technology TATi University College nazri@tatiuc.edu.my
Pointer • After completing this chapter student should be able to:-
What Are Pointers? • A pointer is a variable that contains a memory address. • For example, if x contains the address of y, then x is said to "point to" y. • Pointer declaration • type *var-name; • For example, to declare p to be a pointer to an integer, use this declaration: • int *p; • For a float pointer, use • float *p;
The Pointer Operators • There are two special operators that are used with pointers: * and &. • The & is a unary operator that returns the memory address of its operand. • balptr = &balance; puts into balptr the memory address of the variable balance. • The * is a unary operator that returns the value of the variable located at the address • value = *balptr; will place the value of balance into value.
Consider the following program:- • #include <iostream> • using namespace std; • int main() • { • int balance; • int *balptr; • int value; • balance = 3200; • balptr = &balance; • value = *balptr; • cout << "balance is: " << value << '\n'; • return 0; • }
Figure 6-1 depicts the actions of the two preceding statements.
The Pointer Operators(2) • What is the output of the program above? Balance is : 3200
The Base Type Is Important • Your pointer variables must always point to the correct type of data. • When you declare a pointer to be of type int, the compiler assumes that anything it points to will be an integer value. • For example, the following fragment is incorrect: int *p; double f; // ... p = &f; // ERROR
The Base Type Is Important(2) • You can override this restriction (at your own risk) by using a cast. For example, the following fragment is now technically correct: int *p ; double f; // ... p = (int *) &f; // Now technically OK • To better understand why using a cast to assign one type of pointer to another is not usually a good idea, consider the following short program:
// This program will not work right. • #include <iostream> • using namespace std; • int main() • { • double x, y; • int *p; • x = 123.23; • p = (int *) &x; // use cast to assign double * to int * • y = *p; // What will this do? • cout << y; // What will this print? • return 0; • }
Assigning Values Through a Pointer • You can use a pointer to assign a value to the location pointed to by the pointer. • Example. Assuming that p is an integer pointer, this assigns the value 101 to the location pointed to by p: *p = 101; ("at the location pointed to by p, assign the value 101“) • To increment or decrement the value at the location pointed to by a pointer, you can use a statement like this: (*p)++;
Assigning Values Through a Pointer(2) • The following program demonstrates assignment using a pointer. • #include <iostream> • using namespace std; • int main() • { • int *p, num; • p = # • *p = 100; • cout << num << ' '; • (*p)++; • cout << num << ' '; • (*p)--; • cout << num << '\n'; • return 0; • }
The output from the program is shown here. 100 101 100
Pointer Expressions • Pointers can be used in most valid C++ expressions. • Remember also that you may need to surround some parts of a pointer expression with parentheses
Pointer Arithmetic • There are only four arithmetic operators that can be used on pointers: ++, – –, +, and –. • Let p1 be an integer pointer with a current value of 2,000. • After the expression p1++; the contents of p1 will be 2,004, not 2,001! • Each time that a pointer is incremented, it will point to the memory location of the next element of its base type.
Pointer Arithmetic(2) • You can also add or subtract integers to or from pointers. The expression p1 = p1 + 9; makes p1 point to the ninth element of p1’s base type, beyond the one to which it is currently pointing. • To see the effects of pointer arithmetic, execute the next short program.
// Demonstrate pointer arithmetic. • #include <iostream> • using namespace std; • int main() • { • int *i, j[10]; • double *f, g[10]; • int x; • i = j; • f = g; • for(x=0; x<10; x++) • cout << i+x << ' ' << f+x << '\n'; • return 0; • }
Here is sample output. 0012FE5C 0012FE84 0012FE60 0012FE8C 0012FE64 0012FE94 0012FE68 0012FE9C 0012FE6C 0012FEA4 0012FE70 0012FEAC 0012FE74 0012FEB4 0012FE78 0012FEBC 0012FE7C 0012FEC4 0012FE80 0012FECC
Pointer Comparisons • Pointers may be compared by using relational operators, such as ==, <, and >. • If p1 and p2 are pointers that point to two separate and unrelated variables, then any comparison between p1 and p2 is generally meaningless. • If p1 and p2 point to variables that are • related to each other, such as elements of the same array, then p1 and p2 can be meaningfully compared.
Pointers and Arrays • In C++, there is a close relationship between pointers and arrays. • In fact, frequently a pointer and an array are interchangeable. • consider this fragment: char str[80]; char *p1; p1 = str; • if you want to access the fifth element in str, you could use:- str[4] or *(p1+4)
Pointers and Arrays(2) • C++ allows two methods of accessing array elements: pointer arithmetic and array indexing. • Pointer arithmetic can sometimes be faster than array indexing. • Example: two versions of the same program will be shown next.
// Tokenizing program: pointer version. • #include <iostream> • #include <cstdio> • using namespace std; • int main() • { • char str[80]; • char token[80]; • char *p, *q; • cout << "Enter a sentence: "; • gets(str); • p = str; • // Read a token at a time from the string. • while(*p) { • q = token; // set q pointing to start of token • /* Read characters until either a space or the • null terminator is encountered. */ • while(*p!=' ' && *p) { • *q = *p; • q++; p++; • } • if(*p) p++; // advance past the space • *q = '\0'; // null terminate the token • cout << token << '\n'; • } • return 0; • } • Here
// Tokenizing program: array-indexing version. • #include <iostream> • #include <cstdio> • using namespace std; • int main() • { • char str[80]; • char token[80]; • int i, j; • cout << "Enter a sentence: "; • gets(str); • // Read a token at a time from the string. • for(i=0; ; i++) { • /* Read characters until either a space or the • null terminator is encountered. */ • for(j=0; str[i]!=' ' && str[i]; j++, i++) • token[j] = str[i]; • token[j] = '\0'; // null terminate the token • cout << token << '\n'; • if(!str[i]) break; • } • return 0; • }
Indexing a Pointer • It is possible to index a pointer as if it were an array. • // Indexing a pointer like an array. • #include <iostream> • #include <cctype> • using namespace std; • int main() • { • char str[20] = "hello tom"; • char *p; • int i; • p = str; // put address of str into p • // now, index p like an array • for(i=0; p[i]; i++) p[i] = toupper(p[i]); • cout << p; // display the string • return 0; • }
The program displays HELLO TOM • Remember, the expression p[i] is functionally identical to *(p+i).
Are Pointers and Arrays Interchangeable? • Pointers and arrays are interchangeable in many cases, but not completely. Consider this fragment: int num[10]; int i; for(i=0; i<10; i++) { *num = i; // this is OK num++; // ERROR -- cannot modify num }
Pointers and String Literals • The following program demonstrate how pointer is used with string literals. #include <iostream> using namespace std; int main() { char *s; s = "Pointers are fun to use.\n"; cout << s; return 0; }
A Comparison Example • It is legal to compare the value of one pointer to another (which is point to elements of the same array). • The following program demonstrates a pointer comparison. // A pointer comparison example. #include <iostream> using namespace std; int main() { int num[10]; int *start, *end; start = num; end = &num[9];
// enter the values while(start <= end) { cout << "Enter a number: "; cin >> *start; start++; } start = num; // reset the starting pointer // display the values while(start <= end) { cout << *start << ' '; start++; } return 0; }
Arrays of Pointers • Pointers can be arrayed like any other data type. For example, int *ipa[10]; //each element in ipa holds a pointer to an int value. • To assign the address of an int variable called var to the third element of ipa ipa[2] = &var; • Using the ipa array to assign the value of var to an int variable called x x = *ipa[2];
Arrays of Pointers(2) • Like other arrays, arrays of pointers can be initialized. char *fortunes[] = { "Soon, you will come into some money.\n", "A new love will enter your life.\n", "You will live long and prosper.\n", "Now is a good time to invest for the future.\n", "A close friend will ask for a favor.\n" }; • Thus, to print the second message, use a statement like this: cout << fortunes[1];
The Null Pointer Convention • Any type of pointer should be initialized to null when it is declared. For example, the following initializes p to null: float *p = 0; // p is now a null pointer • If you follow the null pointer convention, you will avoid many problems when using pointers.
Problems with Pointers • When a pointer accidentally contains the wrong value, it can be the most difficult bug to track down. • The classic example of a pointer error is the uninitialized pointer. Consider this example: // This program is wrong. int main(){ int x, *p; x = 10; *p = x; // where does p point? return 0; } //You will have no way of knowing where the value of x has been written.
Passing Arguments to Functions by Reference with Pointers • There are three ways in C++ to pass arguments to a function:- • pass-by-value • pass-by-reference (with pointer) • Figure 8.6 and Figure 8.7 present two versions of a function that cubes an integercubeByValue and cubeByReference
Cube a variable using pass-by-value. 2 // Cube a variable using pass-by-value. 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 int cubeByValue( int ); // prototype 8 9 int main() 10 { 11 int number = 5; 12 13 cout << "The original value of number is " << number; 14 15 number = cubeByValue( number ); // pass number by value to cubeByValue 16 cout << "\nThe new value of number is " << number << endl; 17 return 0; // indicates successful termination 18 } // end main 19
Cube a variable using pass-by-value.(cont) 20 // calculate and return cube of integer argument 21 int cubeByValue( int n ) 22 { 23 return n * n * n; // cube local variable n and return result 24 } // end function cubeByValue Output The original value of number is 5 The new value of number is 125
Cube a variable using pass-by-reference with a pointer argument. 2 // Cube a variable using pass-by-reference with a pointer argument. 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 void cubeByReference( int * ); // prototype 8 9 int main() 10 { 11 int number = 5; 12 13 cout << "The original value of number is " << number; 14 15 cubeByReference( &number ); // pass number address to cubeByReference 16 17 cout << "\nThe new value of number is " << number << endl; 18 return 0; // indicates successful termination 19 } // end main
Cube a variable using pass-by-reference with a pointer argument(cont) 21 // calculate cube of *nPtr; modifies variable number in main 22 void cubeByReference( int *nPtr ) 23 { 24 *nPtr = *nPtr * *nPtr * *nPtr; // cube *nPtr 25 } // end function cubeByReference Output The original value of number is 5 The new value of number is 125
Calling Functions with Arrays • When an array is an argument to a function, only the address of the first element of the array is passed. • Remember- in C++, an array name without an index is a pointer to the first element in the array.) • Examine the following example. To call display( ), pass the address of the array as the first argument, and the size of the array as the second.
#include <iostream> using namespace std; //void display(int *, int ); void display(int *num,int n) { int i; for(i=0; i<n; i++) cout << num[i] << ' '; } int main() { int t[10],i; for(i=0; i<10; ++i) t[i]=i; display(t,10); // pass array t and it size to a function return 0; }
Summary • Pointers are variables that contain as their values memory addresses of other variables. • The declarationint *ptr; declares ptr to be a pointer to a variable of type int and is read, "ptr is a pointer to int." The * as used here in a declaration indicates that the variable is a pointer. • There are three values that can be used to initialize a pointer: 0, NULL or an address of an object of the same type. Initializing a pointer to 0 and initializing that same pointer to NULL are identical0 is the convention in C++.
Summary(2) • The & (address) operator returns the memory address of its operand. • A function receiving an address as an argument must have a pointer as its corresponding parameter. • There are four ways to pass a pointer to a functiona nonconstant pointer to nonconstant data, a nonconstant pointer to constant data, a constant pointer to nonconstant data and a constant pointer to constant data. • The value of the array name is the address of (a pointer to) the array's first element.
Summary(3) • To pass a single element of an array by reference using pointers, pass the address of the specific array element. • The arithmetic operations that may be performed on pointers are incrementing (++) a pointer, decrementing (--) a pointer, adding (+ or +=) an integer to a pointer, subtracting (- or -=) an integer from a pointer and subtracting one pointer from another. • When an integer is added or subtracted from a pointer, the pointer is incremented or decremented by that integer times the size of the object to which the pointer refers.
Summary(4) • Pointers can be compared using the equality and relational operators. Comparisons using relational operators are meaningful only if the pointers point to members of the same array. • Pointers that point to arrays can be subscripted exactly as array names can.