300 likes | 308 Views
Learn about pointers, a powerful feature of C programming. Understand how pointers enable dynamic data structures and simulate call-by-reference. Explore pointer declarations, initialization, operators, and more.
E N D
Department of Computer and Information Science,School of Science, IUPUI CSCI 230 Pointers Dale Roberts, Lecturer Computer Science, IUPUI E-mail: droberts@cs.iupui.edu
CS A B C D Address of next location What is Pointer CS Dept. Location A: Highway Intersection Location C: Crabapple Tree Bring your money to IUPUI ET-202 to exchange hostage Phone rings and says “Deliver ransom to I-65 and West St. intersection “Find next message on the top of traffic light on Michigan St. and West St. Location D: IUPUI ET-202 “Find Instruction Under The crabapple tree next to old law school ” Location B: Traffic Light Hostage A pointer is an address.
Pig Pen Lucy Sally Linus Charlie Woodstock “Sally knows” “ Linus knows ” “ Lucy knows ” “ Charlie knows ” “ Snoopy is ” Snoopy Woodstock is with Snoopy … Snoopy Linus Charlie What is Pointer Example: Find out who is with Woodstock among peanut gang? Pig Pen points to Lucy; Lucy points to Sally; Sally points to Linus; Linus points to Charlie; Charlie points to Snoopy; Snoopy has Woodstock An instance uses a pointer to link to a next instance making a chain.
Pointer declarations: datatype snoopy, *charlie, **linus; snoopy= ; /* snoopy’s content is Woodstock */ charlie= &snoopy; /* charlie’s content is the info (pointer) to locate snoopy, which is snoopy’s address*/ linus= &charlie; /* linus’s content is the info (pointer) to locate charlie, which is charlie’s address*/ • In general, we can rewrite charlie using variable of snoopyPtr (Snoopy’s pointer)and rewrite linus using variable of snoopyPtrPtr (pointer to Snoopy’s pointer); • Note that this is only a naming convention. The only requirement is that the variable be a valid identifier: begin with a letter followed by letters, digits or _.
Pointer Variable Declarations and Initialization • Pointers • Definition: A pointer is a variable that contains address of another variable. • Most powerful feature of C, but difficult to master • Pointers enable programs to simulate call-by-reference and create/manipulate dynamic data structures • Close relationship with arrays and strings
count 7 • Pointer variables • Contain memory addresses as their values • Normal variables contain a specific value (direct reference) • Pointers contain address of a variable that has a specific value (indirect reference) • Indirection – referencing a pointer value countPtr count 7
Pointer Variable Declarations • Pointer Declarations type *variable_name • * used with pointer variables Example: int *myPtr; • Declares a pointer to an int (pointer of type int *) • Multiple pointers require using a * before each variable declaration • Can declare pointers to any data type Example: int *myPtr1, *myPtr2; float *pq; char *pc;
ptr x FFFF 5000 x ptr FFFF 5000 10 ptr x FFFF 5000 FFFF 10 Pointer Variable Initialization • Initialize pointers to 0, NULL, or an address • 0 or NULL– points to nothing (NULL preferred) Example: int *ptr, x; x=10; ptr = &x;
yPtr y 5 Pointer Operators • &: Address Operator • Returns address of operand int y = 5; int *yPtr; yPtr = &y; /* yPtr “points to” y */ /* yPtr gets address of y */ yptr y 5 500000 600000 600000 address of y is the value of yPtr
Pointer Operators • * : Indirection / De-referencing Operator • Returns a synonym/alias of what its operand points to • *yptr returns y (because yptr points to y) • * can be used for assignment that returns alias to an object *yptr = 7; // changes y to 7 • Dereferenced pointer (operand of *) must be a variable (no constants) • *and & are inverses • They cancel each other out
1 /* Fig. 7.4: fig07_04.c 2 Using the & and * operators */ 3 #include <stdio.h> 4 5 int main() 6 { 7 int a; /* a is an integer */ 8 int *aPtr; /* aPtr is a pointer to an integer */ 9 a aPtr 10 a = 7; 7 0012FF88 00FFFFFF 0012FF88 11 aPtr = &a; /* aPtr set to address of a */ 12 13 printf( "The address of a is %p" 14 "\nThe value of aPtr is %p", &a, aPtr ); 15 16 printf( "\n\nThe value of a is %d" 17 "\nThe value of *aPtr is %d", a, *aPtr ); 18 19 printf( "\n\nShowing that * and & are inverses of " 20 "each other.\n&*aPtr = %p" 21 "\n*&aPtr = %p\n", &*aPtr, *&aPtr ); 22 23 return 0; 24 } The address of a is the value ofaPtr. The *operator returns an alias to what its operand points to.aPtrpoints toa, so*aPtrreturnsa. Note the use of %p format. 1. Declare variables 2 Initialize variables 3. Print Program Output Notice how*and&are inverses The address of a is 0012FF88 The value of aPtr is 0012FF88 The value of a is 7 The value of *aPtr is 7 Proving that * and & are complements of each other. &*aPtr = 0012FF88 *&aPtr = 0012FF88 ( The address of the variable that aPtr points to ) ( The content in the address location of aPtr )
pi i 902 874 874 5 Pointer Operators Example: int i = 5; int *pi; pi = &i; /* place the address of i into pi */ Assume Symbol Table i.e. &i = 874, i = 5; &pi = 902, pi = 874; *pi = ? *pi = 5; // same as i = 5; *pi = *pi * 2; // same as i = i * 2; *pi *= 2; // same as i *= 2;
ppi pi i 108 104 100 5 104 100 Example: int i,*pi,**ppi; i = 5; pi = &i; ppi = π
Calling Functions by Reference • Call by reference with pointer arguments • Pass address of argument using & operator • Allows you to change actual location in memory • Arrays are not passed with & because the array name is already a pointer • * Operator • Used as alias/nickname for variable inside of function void double_num ( int *number ) { *number = 2 * ( *number ); } • *number used as nickname for the variable passed
1 /* 2 Cube a variable using call-by-value 3 */ 4 5 #include <stdio.h> 6 7 int cubeByValue( int ); /* prototype */ 8 9 int main() 10 { 11 int number = 5; 12 13 printf( "The original value of number is %d", number ); 14 number = cubeByValue( number ); 15 printf( "\nThe new value of number is %d\n", number ); 16 17 return 0; 18 } 19 20 int cubeByValue( int n ) 21 { 22 return n * n * n; /* cube number in main */ 23 } Example of Calling Functions by Value Function prototype Initialize variables Call function Define function Program Output The original value of number is 5 The new value of number is 125
Example of Calling Functions by Value int main() { int number = 5; number = cubeByValue( number ); } int main() { int number = 5; number = cubeByValue( number ); } int main() { int number = 5; number = cubeByValue( number ); } int main() { int number = 5; number = cubeByValue( number ); } int main() { int number = 5; number = cubeByValue( number ); } number int cubeByValue( int n ) { return n * n * n; } int cubeByValue( int n ) { return n * n * n; } int cubeByValue( int n ) { return n * n * n; } int cubeByValue( int n ) { return n * n * n; } int cubeByValue( int n ) { return n * n * n; } n 5 undefined number n 5 5 number n 5 5 125 number n undefined 5 number n 125 undefined
1 /* Fig. 7.7: fig07_07.c 2 Cube a variable using call-by-reference 3 with a pointer argument */ 4 5 #include <stdio.h> 6 7 void cubeByReference( int * ); /* prototype */ 8 9 int main() 10 { 11 int number = 5; 12 13 printf( "The original value of number is %d", number ); 14 cubeByReference( &number ); 15 printf( "\nThe new value of number is %d\n", number ); 16 17 return 0; 18 } 19 20 void cubeByReference( int *nPtr ) 21 { 22 *nPtr = *nPtr * *nPtr * *nPtr; /* cube number in main */ 23 } Example of Calling Functions by Reference Notice that the function prototype takes a pointer to an integer ( int * ). Notice how the address of number is given - cubeByReference expects a pointer (an address of a variable). Function prototype Initialize variables Call function Define function Program Output Inside cubeByReference, *nPtr is used (*nPtr is number). The original value of number is 5 The new value of number is 125
nPtr number address of number 5 address of number 125 Example of Calling Functions by Reference int main() { int number = 5; cubeByReference( &number ); } int main() { int number = 5; cubeByReference( &number ); } int main() { int number = 5; cubeByReference( &number ); } Before the call by reference to cubeByReference: void cubeByReference( int *nPtr ) { *nPtr = *nPtr * *nPtr * *nPtr; } void cubeByReference( int *nPtr ) { *nPtr = *nPtr * *nPtr * *nPtr; } void cubeByReference( int *nPtr ) { *nPtr = *nPtr * *nPtr * *nPtr; } nPtr number undefined 5 After call by reference to cubeByReference and before *nPtr is cubed: n After *nPtr is cubed : nPtr number
COMPUTER MEMORY CONSTANT MEMORY AREA myPtr1 x2 Ptr x3 case 3 case 2 case 1 x1 myPtr2 myPtr x case with using const VARIABLE MEMORY AREA Using the const Qualifier with Pointers • const qualifier • Variable cannot be changed • Use const if function does not need to change a variable • Attempting to change a const variable produces an error • const pointers • Point to a constant memory location • Must be initialized when declared • int *const myPtr1 = &x1; • Type int *const • Constant pointer to an int • x can be changed, but not *Ptr • const int *myPtr2 = &x2; • Regular pointer to a const int • const int *const Ptr = &x3; • const pointer to a const int
1 /* Fig. 7.13: fig07_13.c 2 Attempting to modify a constant pointer to 3 non-constant data */ 4 5 #include <stdio.h> 6 7 int main() 8 { 9 int x, y; 10 11 int * const ptr = &x; /* ptr is a constant pointer to an 12 integer. An integer can be modified 13 through ptr, but ptr always points 14 to the same memory location. */ 15 *ptr = 7; 16 ptr = &y; 17 18 return 0; 19 } Declare variables Declare const pointer to an int Change *ptr (which is x) Attempt to change ptr Output Changing *ptr is allowed – x is not a constant. Changing ptr is an error – ptr is a constant pointer. FIG07_13.c: Error E2024 FIG07_13.c 16: Cannot modify a const object in function main *** 1 errors in Compile ***
Pointer Expressions and Pointer Arithmetic pv+n pv + n*sizeof(variable type that pointer point to) • Arithmetic operations can be performed on pointers • Increment/decrement pointer (++ or --) Example: ++vPtr, vPtr++, --vPtr, vPtr-- • Add an integer to a pointer( + or += , - or -=) • Pointers may be subtracted from each other • Operations meaningless unless performed on an array
location 3000 3004 3008 3012 3016 pointer variablevPtr v[0] v[1] v[2] v[4] v[3] Example: • Five element int array on machine with 4 byte ints • vPtr points to first element v[0]whose address location is 3000 (vPtr = 3000) • vPtr += 2; // sets vPtrto 3008 • vPtr points to v[2] (incremented by 2), but the machine has 4 byte integers, so it points to address 3008
a 5 640 644 10 800 700 648 15 700 640 652 ppa pa 656 660 Pointer Expressions and Pointer Arithmetic Example: (double pointer) Assume long (long integer) is 4 bytes, and pointer variable is 2 bytes. long a[10]={5, 10, 15, …}; long *pa, **ppa; int i=5; pa = &a; ppa = &pa; Questions:
Pointer Expressions and Pointer Arithmetic • Subtracting pointers • Returns number of elements from one to the other. If vPtr2 is a pointer pointing to v[2]; vPtr is a pointer pointing to v[0]; • vPtr2 - vPtr would produce 2 • Pointer comparison ( <, == , > ) • See which pointer points to the higher numbered array element • Also, see if a pointer points to 0 • Pointers of the same type can be assigned to each other • If not the same type, a cast operator must be used • Exception: pointer to void (type void *) • Generic pointer, represents any type • No casting needed to convert a pointer to void pointer • void pointers cannot be dereferenced
The Relationship Between Pointers and Arrays • Arrays and pointers are closely related • Array name like a constant pointer • Pointers can do array subscripting operations Example: Declare an array b[5] and a pointer bPtr bPtr = b; // To set them equal to one another //The array name (b) is actually the address of first element of the array bPtr = &b[0]; // Explicitly assigns bPtr to address of first element of b To access element b[3]: x=*(bPtr+3) // Where n is the offset. Called pointer/offset notation x=bptr[3] // Called pointer/subscript notation // bPtr[3] same as b[3] x=*(b+3) // Performing pointer arithmetic on the array itself
f(int *s) { … } Pointers and Arrays • Strong relation between pointers and arrays • Pointers and arrays can be used interchangeably. • The array name is equivalent to the address of the first element in the array Example: int a[10]; int *pa; pa = &a[0]; /* is equivalent to pa = a */ So, a[1] *(pa+1) pa[1] *(a+1) &a[1] pa+1 a+1 a[i] *(pa+i) pa[i] *(a+i) &a[i] pa+i a+i a[i]+=5 *(pa+i)+=5 pa[i]+=5 Example: f(int s[]) { … }
’\0’ ’\0’ ’\0’ ’\0’ ’o’ ’d’ ’n’ ’u’ ’a’ ’s’ ’b’ ’d’ ’a’ ’s’ ’s’ ’a’ ’i’ ’m’ ’e’ ’r’ ’l’ ’e’ ’s’ ’t’ ’p’ suit[0] ’H’ ’D’ suit[1] ’C’ suit[2] ’S’ suit[3] Arrays of Pointers • Arrays can contain pointers • For example: an array of strings char *suit[4] = {"Hearts", "Diamonds", "Clubs", "Spades"}; • Strings are pointers to the first character • char *– each element of suit is a pointer to a char • The strings are not actually stored in the array suit, only pointers to the strings are stored • suitarray has a fixed size, but strings can be of any size
Pointers to Functions • Pointer to function • Contains address of function • Similar to how array name is address of first element • Function name is starting address of code that defines function • Function pointers can be • Passed to functions • Stored in arrays • Assigned to other function pointers
Example: Bubble Sort #define SIZE 10 void bubble(int [],constint, int (*)(int,int)); int ascending( int, int ); int descending( int, int ); int main() { int a[SIZE] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; bubble( a, SIZE, ascending ); bubble( a, SIZE, descending ); } void bubble( int work[], constint size, int (*compare)(int,int)) { int pass, count; void swap( int *, int * ); for (pass=1; pass<size; pass++) for (count=0; count<size-1; count++) if ((*compare)(work[count],work[count+1])) swap(&work[count],&work[count + 1]); } voidswap( int *element1Ptr, int *element2Ptr ) { int temp; temp = *element1Ptr; *element1Ptr = *element2Ptr; *element2Ptr = temp; } intascending( int a, int b ) { return b < a; /*swap if b is less than a*/ } intdescending( int a, int b ) { return b > a; /*swap if b is greater than a*/ }
Function bubble takes a function pointer • bubble calls this helper function • this determines ascending or descending sorting • The argument in bubblesort for the function pointer: bool ( *compare )( int, int ) tells bubblesort to expect a pointer to a function that takes two ints and returns a bool • If the parentheses were left out: bool *compare( int, int ) • Declares a function that receives two integers and returns a pointer to a bool