Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 6 Pointers C Programming © 2003 by The McGraw-Hill Companies, Inc. All rights reserved.

Similar presentations


Presentation on theme: "Chapter 6 Pointers C Programming © 2003 by The McGraw-Hill Companies, Inc. All rights reserved."— Presentation transcript:

1 Chapter 6 Pointers C Programming © 2003 by The McGraw-Hill Companies, Inc. All rights reserved.

2 2 Pointers Pointers are one of C/C++’s most important and troublesome features. They provide support for very powerful facilities such as: dynamic memory allocation and the creation of linked lists. dynamic memory allocation and the creation of linked lists. Allowing a function to modify the contents of an argument that has been passed to it ( pass-by-pointer ). Allowing a function to modify the contents of an argument that has been passed to it ( pass-by-pointer ). In this chapter however, we will learn the basics of pointers, how to manipulate them, and avoid potential problems.

3 3 What are Pointers? A pointer is a variable that contains a memory address. Usually this address is the location in memory of another variable. For example, if pointer variable x contains the address of the variable y, then x is said to "point to" y. ???? Memory Pointer x int y; In the example above the variable declaration (y) allocates 4 bytes of memory. Notice that the pointer (x) points to the first byte of memory allocated to the integer variable.

4 4 Pointer Declaration A pointer declaration is declared almost in the same manner as a regular variable. The only difference is that the name of the pointer must be preceded by an asterisk ( * ). The general syntax is: Examples of declaring pointers: type *var-name; int *iptr; // define an integer pointer float *fptr; // define a float pointer char *cptr; // define a character pointer double *dptr; // define a double pointer int *ptr = null; // define & initialize a pointer Note that type used for the pointer indicates the data-type ( base type) of the variable it will point to.

5 5 Pointer Operators There are two special operators used with pointer: * a unary operator used the dereference a pointer & a unary operator that returns the memory address of its operand usually called “the address of “ operator. For example: The above places the memory address of the variable balance into the pointer variable balPtr. The contents of balPtr is the memory address of balance and has nothing to do with the actual contents of balance. float balance; // define a float variable float *balPtr; // define a float pointer variable balPtr = &balance; // set the pointer balPtr to the // address of the variable balance

6 6 Pointer Operators (continued) Assume the variable balance starts at memory address 1000, and contains the value 567.33. The following represents what the variables will contain: What will the following code do? float balance; float *balPtr; 567.33 1000 cout << *balPtr << endl; This code says, display the contents of the float variable ( balance ) pointed to by the pointer variable balPtr. The * operator returns the value of the variable located at the address specified by its operand. This is usually referred to as dereferencing a pointer.

7 7 Pointer Operators (continued) The float variable value will be set to the contents of the float variable pointed to by the float pointer balPtr. What will the following code do? float value; value = *balPtr; The contents of the float variable pointed to by the float pointer balPtr will be set to the value 891.62. What will the following code do? *balPtr = 891.62F;

8 8 Pointer Operators (continued) Here is a sample program using pointers: #include using namespace std; int main() { float balance; float *balptr; float value; balance = 3200; balptr = &balance; value = *balptr; // dereference balPtr cout << "balance is: " << value << '\n'; return 0; } OUTPUT: balance is: 3200

9 9 Notes About Pointers 1. Note that symbol used for the “at address” operator ( * ) is the same symbol used for multiplication. This can be confusing. These operators have NO relationship to each other. 2. The & and * have a higher precedence than any of the arithmetic operators (therefore the multiplication operator) except the unary minus, with which they have equal precedence. 3. The act of using a pointer is often called indirection because you are accessing one variable indirectly through another variable. 4. To find the address of a variable use the & operator. 5. If x is a variable, then &x is the address of x in memory. 6. To gain access to the object that a pointer points to use the * indirect operator. This is usually called dereferencing a pointer. If p is a pointer, then *p represents the object to which p currently points.

10 10 The Base Type Is Important How does C/C++ know how many bytes to copy into value from the address pointed to by balPtr in the following? The answer is that the base type of the pointer determines the type of data that the compiler assumes the pointer is pointing to. Because balPtr is a float pointer C/C++ copies 4 bytes of information into value from the address pointed to by balPtr. You should ALWAYS make sure any pointer variable points to the correct type of data. The help you C/C++ will not allow you to assign one type of pointer to another unless the types of the pointers are the same. The following code is incorrect: value = *balPtr; int *p; double f; //... p = &f; // ERROR

11 11 The Base Type Is Important (continued) You can override this restriction, if and when necessary, by using a cast. The following is technically correct: This may pose a problem because, even though p is actually pointing to a floating-point value, the computer still “thinks” that p is pointing to an integer (because p is an integer pointer). int *p ; double f; //... p = (int *) &f; // Now technically OK Using a cast to assign one type of pointer to another is not usually a good idea.

12 12 The Base Type Is Important (continued) Consider this program. // This program will not work right. #include 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; } OUTPUT: ????????

13 13 Assigning Values Through a Pointer A pointer can be used on the left side of the assignment operator to assign a value to the location pointed to by the pointer. This says, assign the value 101 to location (hopefully an integer) pointed to by p. To increment or decrement the value pointed to by a pointer you can use the following: The parentheses are required because the * operator has a lower precedence than the ++ operator. Without the parentheses, the address stored in the pointer variable p would be incremented by 1. (*p)++; int *p; *p = 101;

14 14 Assigning Values Through a Pointer A sample program: #include using namespace std; int main() { int *p, num; p = &num; *p = 100; cout << num << ' '; (*p)++; cout << num << ' '; (*p)--; cout << num << '\n'; return 0; } OUTPUT: 100 101 100

15 15 Pointer Expressions Pointers can be used in most VALID C/C++ expressions, but remember this special rule: You may need to surround some parts of a pointer expression with parentheses to obtain the desired results.

16 16 Pointer Arithmetic There are only four arithmetic operators that can be used on pointers: ++ ++ -- -- + - If p1 is an integer pointer with a value of 2,000 then after the expression the contents of p1 will be 2,004, not 2,001. Each time p1 is incremented, it will point to the next integer in memory. This is also true for the decrement operator. For char pointers, an increment/decrement will be as “normal” arithmetic because characters are one byte long. Every other type of pointer will increase/decrease by the length of its base type. p1++;

17 17 Pointer Arithmetic (continued) You can also add and subtract integers to or from pointers. The expression makes p1 point to the ninth element of p1's base type, beyond the one it is currently pointing to. You cannot add two pointers, but you can subtract one pointer from another pointer provided the are of the same base type. The result will be the number of elements of the base type that separate the two pointers. p1 = p1 + 9; Remember: All pointer arithmetic is performed relative to the base type of the pointer. All pointer arithmetic is performed relative to the base type of the pointer.

18 18 A demonstration program: #include 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; } OUTPUT: 0012FEB0 0012FE5C 0012FEB4 0012FE64 0012FEB8 0012FE6C 0012FEBC 0012FE74 0012FEC0 0012FE7C 0012FEC4 0012FE84 0012FEC8 0012FE8C 0012FECC 0012FE94 0012FED0 0012FE9C 0012FED4 0012FEA4

19 19 Pointers and Arrays In C/C++ pointers and arrays are frequently interchangeable. An array name without an index generates a pointer to the start of the array. Consider the following: An array name ALWAYS points to the first element of the array. This is VERY important to understand. Because of this, a pointer can be used to access the elements of an array. Both of the following statements access element 5 of the array. char str[80]; char *p1; p1 = str; // assigns p1 to point to str[0] str[4] OR *(p1 + 4) // why the parentheses? The * operator has a higher precedence than the + operator.

20 20 Pointers and Arrays C/C++ allows two methods of accessing array elements: Pointer arithmetic Pointer arithmetic Array indexing Array indexing Pointer arithmetic can be faster than array indexing—especially if the array is being processed sequentially. The next two sample programs demonstrate both methods.

21 21 Tokenizing program: pointer version. #include 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 a space or the null terminator is encountered. while( *p != ' ' && *p ) { *q = *p; q++; p++; } if( *p ) // advance past the space p++; *q = '\0'; // null terminate the token cout << token << '\n'; } return 0; }

22 22 Tokenizing program: array-indexing version. #include 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 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; }

23 23 Indexing a Pointer In C/C++, it is possible to index a pointer as if it were an array. Here is an example: #include using namespace std; int main() { char str[20] = "hello tom"; char *p; int i; p = str; for(i=0; p[i]; i++) // index a pointer p[i] = toupper(p[i]); cout << p; // display the string return 0; } OUTPUT: HELLO TOM The toupper() function converts a lower case character to uppercase.

24 24 Are Pointers and Arrays Interchangeable? Pointers and arrays are strongly related, and are interchangeable in many cases. But, they are not completely interchangeable. For example: int num[10]; int i; for(i = 0; i < 10; i++) { *num = i; // this is OK num++; // ERROR -- cannot modify num } num is an array of integers. It is illegal to modify num's value. The reason is that num is a constant that points to the beginning of an array. Thus you cannot increment it. While an array name generates a pointer to the beginning of an array, it cannot be changed. It can still be used in pointer-style expressions, as long as it is not modified. *(num + 3) = 100; // This is OK because num is not changed

25 25 Pointers and String Literals How does C/C++ handle string literals? cout << strlen( "C++ Compiler" ); When the compiler encounters a string literal like "C++ Compiler" above, it stores it in the program's string table and generates a pointer to the string. Therefore the following program is valid: #include using namespace std; int main() { char *s; s = "Pointers are fun to use.\n"; cout << s; return 0; } The string table is a table generated by the compiler and holds the strings used by your program. These strings are constants and attempting to change them will result in a run-time error.

26 26 A Comparison Example When the compiler encounters a string literal like "C++ Compiler" above, it stores it in the program's string table and generates a pointer to the string. Therefore the following program is valid:

27 27 An example of comparing pointers. #include using namespace std; int main() { int num[10]; int *start, *end; start = num; end = &num[9]; while( start <= end ) { cout << "Enter a number: "; cin >> *start; start++; } start = num; // reset the starting pointer while( start <= end ) { cout << *start << ' '; start++; } return 0; }

28 28 Arrays of Pointers You can create arrays of pointers just like any other data type. int *ipa[10]; This declares an array of 10 integer pointers. Each element in the array is a pointer to an int value. To assign the address of an int variable called var to the third element of the array ipa, you would: ipa[2] = &var; x = *ipa[4]; Using the ipa array to assign the value of the integer pointed to by the integer pointer in the fifth element of the array to the integer variable x you would code:

29 29 Initializing Arrays of Pointers You can initialize an array of pointers. A common use for this is to hold pointers to strings. 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" }; The next slide shows the entire "fortune cookie" program. It uses the rand() function to generate a random number then uses the modulus operator to obtain a number from 0 to 4. This value is used to display one of the messages from the array. cout << fortunes[1]; // displays the second message Since string literals are stored in the string table, the array only needs to store pointers to the strings not the strings themselves.

30 30 #include using namespace std; 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" }; int main() { int chance; cout << "To see your fortune, press a key: "; // randomize the random number generator while( !kbhit() ) rand(); cout << '\n'; chance = rand(); chance = chance % 5; cout << fortunes[chance]; return 0; }

31 31 #include using namespace std; char *keyword[][2] = { // create a table "for", "for(initialization; condition; increment)", "if", "if(condition)... else...", "switch", "switch(value) { case-list }", "while", "while(condition)...", // add the rest of the C++ keywords here "", "" // terminate the list with nulls }; int main() { char str[80]; int i; cout << "Enter keyword: "; cin >> str; for( i = 0; *keyword[i][0]; i++ ) // display syntax if( !strcmp( keyword[i][0], str ) ) cout << keyword[i][1]; return 0; } Sample execution: Enter keyword: for for(initialization; condition; increment) A simple C++ keyword synopsis program:

32 32 The Null Pointer Convention After a pointer is declared, but before it has been assigned a value, it will contain junk. If you use a pointer before giving it a value, bad things happen to your program and/or the operating system. By convention, if a pointer contains a null (zero) value, it is assumed to point to nothing. If all unused pointers are set to null and you avoid the use of null pointers, you can avoid bad things happening to your program. This is a good practice to follow. You can initialize any pointer to null when it is declared. To check for a null pointer, use an if statement float *p = 0; // p is now a null pointer if( p ) // succeeds if p is not null if( !p ) // succeeds if p is null

33 33 Multiple Indirection A pointer to a pointer is a form of multiple indirection, or a chain of pointers (is this heavy or what?). Usually a pointer contains the address of a value (Single Indirection below). PointerVariable Pointer Variable address value Single Indirection address value Multiple Indirection

34 34 Problems with Pointers Pointers provide great power and are very useful in many ways, but when a pointer gets messed up it can be very hard to find the error. Some common causes of problems using pointers: uninitialized pointers uninitialized pointers invalid pointer comparisions invalid pointer comparisions forgetting to reset a pointer forgetting to reset a pointer


Download ppt "Chapter 6 Pointers C Programming © 2003 by The McGraw-Hill Companies, Inc. All rights reserved."

Similar presentations


Ads by Google