Pointers A pointer is a variable that contains memory address as its value. A variable directly contains a specific value. A pointer contains an address of a variable that contains a specific value. We use pointers extensively to create and manipulate dynamic data structures ( linked lists, queues, stacks, and trees), and to simulate call by reference.
Pointer Pointers should be initialized either when they are declared or in an assignment statement. Pointer can be initialized to 0, NULL, or an address. A pointer with the value NULL points to nothing. Initializing a pointer to 0 is equivalent to initializing to NULL (NULL is preferred); NULL is a symbolic constant defined in header file.
Representation of a Pointer int x = 84; // declaration int *ptr; // declaration ptr = &x; 84 ptr x 84 x X directly references a variable whose value is 84 ptr indirectly references a variable whose value is 84 Assigned the address of the variable x to pointer variable ptr. Direct value of ptr is the address of x.
Representation of x and ptr in memory int x = 84; // declaration int *ptr; // declaration ptr = &x; // assigned the address of the // variable x to pointer variable ptr ptr Ptr indirectly references a variable whose value is x X directly references a variable whose value is
Example #include void determine_sign(double num, char *signp); int main(void) { double value; char sn; cout ”; cin >>value; determine_sign( value, &sn); cout << “The sign of “ << value << “is “ << sn <<endl; return (0); }
Example void determine_sign(double num, char *signp) { if (num < 0) *signp = ‘-’; else if (num == 0) *signp = ‘ ‘; else *signp = ‘+’; }
Different ways to pass arguments to a function Two ways to invoke functions: –Call by value –Call by reference Call by value: When arguments are passed call by value, –a copy of the argument’s value is made and passed to the called function. –Changes to the copy do not affect an original variable’s value in the caller.
Call by Reference When an argument is passed by reference, the caller actually allows the called function to modify the original variable’s value. It is possible to simulate call by reference by using address operators and indirection operators.
Cube a variable using call by value #include int cubeByValue(int); int main() { int number1, number = 5; cout << “The original value of number is “<< number <<endl; number1 = cubeByValue(number); cout << “The new value of number is “<< number << endl; cout << “The value of number1 is “<< number1 << endl; return 0; } int cubeByValue(int n) { return n * n * n; }
Cube a variable using call by reference #include void cubeByReference(int *); int main() { int number = 5; cout << “The original value of number is “<< number <<endl; cubeByReference(&number); cout << “The new value of number is “<< number << endl; return 0; } void cubeBy Reference(int *nPtr) { *nPtr = *nPtr ** nPtr * *nPtr; }
Pointer Arithmetic A limited set of arithmetic operators may be performed on pointers. A pointer may be incremented (++) or decremented (--). An integer may be added to a pointer (+ or +=). An integer may be subtracted from a pointer (+ or +=). One pointer may be subtracted from another.
Example int a[5]= {1,2,3,4,5}; int *ptr; ptr = a; When an integer is added to or subtracted from a pointer, the pointer is not simply incremented or decremented by that integer. It depends on the size of the object a pointer point to => machine dependent a + 1a + 3 ptr a
Example (Increment) When an integer is added to a pointer, the pointer is incremented by that integer times the size of the object to which the pointer points to. int *ptr; ptr = a; ptr += 2; will produce: 3008 ( * 4) integer is stored in 4 bytes of memory a + 1 a + 3 ptr a
Example (Decrement) When an integer is subtracted from a pointer, decremented by that integer times the size of the object to which the pointer points to. int *ptr; ptr = a; ptr += 2; ptr -= 1; will produce: 3004 ( * 4) integer is stored in 4 bytes of memory a + 1 a + 3 ptr a
Subtraction Pointer variables may be subtracted from one another. ptr1 contains the location ptr2 contains the location x = ptr2 - ptr1; = 2 will assign to x the number of array elements from ptr1 to ptr ptr2ptr1 a
Relationship between Pointers and Arrays Arrays and Pointers are intimately related in C. Array subscripting notation is converted to pointer notation during compilation. Array name is a pointer to the first element of the array. ptr = &a[0] *(ptr + 3) a[3] &a[3] (ptr + 3) a += 2 invalid => attempts to modify the value of array name with pointer arithmetic a[1]a[3] ptr a Offset to the pointer
Array of Pointers Array may contain pointers (e.g. string array). In C, string is essentially a pointer to its first character. Each entry in an array of strings is actually a pointer to the first character of a string. Example: char *names[4] = {“John”, “Cynthia”, “David”, “Daniel”}; names[4] => an array of 4 elements. char * => each element of array names is of type “pointer to char.” Four array elements are: “John”, “Cynthia”, “David”, “Ruben”. Each of these are stored in memory as a NULL-terminated character string that is one character longer than the number of characters between quotes. E.g. Four strings are 5, 8, 6, and 7.
Example of array of pointers It seems that the strings are placed in the names array, Actually, only the pointers are stored in the array. Each pointer points to the first character of its corresponding string. Names is a fixed size array. However it provides access to character strings of any length. Names could have been placed into a double array of fixed number of columns per row => memory could be wasted. ‘J’‘\0’ ‘D’ ‘h’ ‘C’ ‘n’ ‘y’‘n’ ‘o’ ‘\0’‘a’‘i’‘h’ ‘n’ ‘i’‘v’‘a’ ‘t’ ‘l’‘a’‘D’ ‘\0’‘d’ ‘e’ ‘i’ ‘\0’ names[0] names[1] names[2] names[3]
Pointer to Functions Pointer to a function contains the address of the function in memory. A function name is really the starting address in memory of code that performs the function’s task. Pointers to functions can be passed to functions, returned from functions, stored in arrays, and assigned to another function pointers. int (*compare)(int num[1], int num[4]) Parenthesis s are needed around *compare because * has lower precedence than parentheses enclosing the function parameters.