E N D
Pointers Pointer - A pointer is a derived data type; that is it is a data type built from one of the standard types. Its value is any of the addresses available in the computer for storing and accessing data. Just as the value of an integer constant can be stored in an integer (int) variable and a character constant can be stored in a character (char) type variable, pointer constants (memory addresses) can be stored in a pointer variable. Just as integer constants are made up of a set of whole numbers, character constants are made up of ASCII characters, pointer constants are drawn from the set of addresses for a computer.We cannot change these constants , we can only use them. Pointer Declaration - use the following syntax for declaring a pointer type: type *identifier ; The type can be any standard or user defined type available to the programmer. When the pointer variable is declared a specific type it can only hold the address of a variable of that type. The “ * “ is the indirection operator but when used in the declaration it is a syntactical notation that tells the compiler to set aside space in memory to hold an address. The identifier can be any name following the C naming rules for identifiers. Some examples: char *a ; /* declares a pointer to a char type */ int *x ; /*declares a pointer to a int type */
Pointers • Storing values in pointers - A pointer holds the address of a variable in its contents. A pointer variable can be initialized at the time of declaration or can be assigned a value during execution. • /* declarations */ • int x ; • int *px = &x; • char a ; • char *pa; • /* statements */ • pa = &a ; • One of the most common causes of errors in programming, by novices and professionals alike, is uninitialized pointers. These errors can be very difficult to debug because the effect of the error is often delayed until later in the program execution. A pointer variable can also be set to NULL , either during declaration or execution. This is used if we do not want the pointer to point anywhere. The NULL pointer constant is defined in the standard input/output <stdio.h> library. • Example: • int *px = NULL ;
Pointers Accessing Variables through Pointers - To reference the value of a variable that a pointer points to, you use the unary indirection operator “ * “. The * has a completely different meaning when it is used as the unary indirection operator in the function body. When you dereference a pointer, you are using its value (address ) to reference another variable. The result is an expression that can be used to access the pointed variable for the purpose of inspection or alteration. To access a through the pointer pa, you would use the following expression: *pa The result of the above expression is the value stored in the contents of the variable a. The indirection operator is a unary operator whose operand must be a pointer value.When the indirection operator is used in the right hand side of the assignment operator, it can only inspect (copy) the contents of the variable pointed to. When it is used in the left-hand side of the assignment operator, it can alter the contents of the variable pointed to.
Pointers Remember that declaring a variable in a C program has the effect of telling the compute to set aside an area in memory to store a value: int x = 45 ; int y = 87 ; char z = ‘C’ ; char a = ‘D’ ; The expression &y evaluates to the address of where the contents of y are stored in memory or 6542. The unary operator & is the address of operator. C allows us to declare variables that can have a memory address as it’s contents. int *ypoint ; /* declare a type pointer to an int */ char *zpoint ; /* declare a type pointer to a char */ ypoint = &y ; /* store the address of y in ypoint */ x = * ypoint ; /* assign the contents of the cell that ypoint points to, to the variable x */ Address Contents 0 1 2 6540 45 x y 6542 87 z 6544 C 6545 D a 6546 6542 ypoint Indirection operator
Pointers • #include<stdio.h> • void main(void) • { • int x, y, z; • int *a, *b; • x = 1; y = 2; z = 3; • a = &x; b = &z; • *a += x; • z = y * *a; • b = &x; • *b = *a + *b; • a = &y; • *a = *b = z = 1; • } x y z *a *b
#include <stdio.h> void main(void) { int num1 = 0; int num2 = 0; int *pnum = NULL; pnum = &num1; /* get address of num1 */ *pnum = 2; /*set num1 to 2 */ ++num2; /* increment num2 */ num2 += *pnum; /* add num1 to num2 */ pnum = &num2; /* get address of num2 */ ++*pnum; /* increment num2 indirectly*/ printf("\n num1 = %d num2 = %d\n",num1, num2); printf("*pnum = %d *pnum + num2 = %d", *pnum, *pnum + num2); } OUTPUT: num1 = 2 num2 = 4 *pnum = 4 *pnum + num2 = 8
Pointers Pass by Reference When you need to change the contents in a variable in the calling function, you must pass by reference. In the “Pass by value, a function can return only one value. The solution is to pass the addresses of the variables and let the called function use these addresses to store the values directly in the calling function ‘s variables (local variables). To pass an address we use the address of operator ( & ) which returns the address of the variable operand. A call to a function exchange, that accepts two addresses of integer variables would look like this: exchange( &x, &y ); This calls the function exchange and passes the addresses of x and y to the function. To tell the compiler that we want to store data at an address, we use the indirection operator ( * ). The following statement in function exchange would store the number 5 in the contents of a’s memory cell: *a = 5; Because the contents of a is an address to an integer, C requires us to declare the variable a’stype as an address to an integer (pointer). The following should appear in the parameter list of the function exchange. int *a;
Pointers int main(void) { void exchange(int *a, int *b ); int x = 5; int y = 6; exchange(&x , &y ); return 0; } Main function memory space Addresses 48682 5 x 6 48683 y 6 48684 5 48685 48686 . . . 48683 48684 exchange function memory space Addresses void exchange(int *a, int *b ) { int hold; hold = *a ; *a = *b ; *b = hold ; return; } 48683 37275 a 48684 37276 b 37277 5 hold 37278 37279
Pointers Functions Returning Pointers - a function can return a pointer through the return statement. int main(void) { int *smaller(int *a, int *b ); int x; int y; int *p; scanf(“%d %d”,&x , &y ); p = smaller (&x, &y); return 0; } Main function memory space Addresses 48682 x 48683 y 48687 48691 p 48692 78269 int *smaller(int *a, int *b ); { return (*a < *b ? a : b); } a 48683 78270 b 78274 48687 78275 78276 When you return a pointer, it must point to data in the calling or higher level functions. It is a serious error to return a pointer to a local variable in the called function because when the function terminates, its memory may be used by other parts of the program.
Pointers Pointers to Pointers It is possible to use pointers that point to other pointers. For instance, we can have a pointer pointing to a pointer to and integer. int x ; int *px; int **ppx ; /*statements */ x = 58 ; px = &x ; ppx = &px ; printf(“%3d”, x ); printf(“%3d”, *px ); printf(“%3d”, **ppx); Output: 58 58 58 Each level of pointer indirection requires a separate indirection operator when it is dereferenced. integer variable x 234560 58 pointer to integer 287650 234560 px 287870 ppx 287650 pointer to pointer to integer
Pointers The void Pointer - With one exception, it is invalid to assign a pointer of one type to a pointer of another type. This is true even though the values in both cases are memory addresses and would therefore seem to be fully compatible. Although the addresses may be compatible because they are drawn from the same set, what is not compatible in the underlying data type of the referenced object. C doesn’t let us use the assignment operator with pointers of different types; is we try to , we get a compile error. The exception to the rule is the void pointer. The void pointer can be used with any pointer and any pointer can be assigned to a void pointer. A void pointer cannot be dereferenced. Example: void *pVoid ; Arrays and pointers - There is a very close relationship between arrays and pointers. The name of an array is a pointer constant to the first element. Because the array’s name is a pointer constant, its value cannot be changed. Since the array name is a pointer constant to the first element, the address of the first element and name of the array both represent the same location in memory. We can, therefore, use the array name anywhere we can use a pointer, as long as you do not try to change it’s value. If we have the following declaration: int x[ 5 ] ; the following two expressions result in the same value x &x[0] Also dereferencing the array name gives the same value as a reference to the first element of the array: *x x[0] same same
Pointers Arrays and pointers (continued) - Since the name of the array is a pointer value we can assign this value to other pointer variables of the same type and then use the pointer the same way we use the array name. int main(void) { int a[ 5 ] = {2, 4, 6, 8, 22}; int *p = a; int i = 0; printf(“%d %d\n”, a[i], *p) return 0; } Main function memory space Addresses a[0] 2 48682 4 48683 a[1] 48687 6 a[2] 8 48691 a[3] a[4] 48692 22 2 2 int main(void) { int a[ 5 ] = {2, 4, 6, 8, 22}; int *p; p = &a[1]; printf(“%d %d\n”, a[0], p[-1]); printf(“%d %d\n”, a[1], p[0]); return 0; } 2 2 4 4
Pointers Pointer arithmetic and arrays - Besides indexing, there is another powerful method of moving through an array: Pointer arithmetic. Pointer arithmetic offers a restricted set of arithmetic operators for manipulating the addresses in pointers. It is especially powerful when we need to move through an array from element to element, such as when we are searching an array sequentially. If we have an array, a, then a is a constant pointing to the first element and a + 1 is a constant to the second element. If we have a pointer, p, pointing to the second element of an array , then p - 1 is a pointer to the previous (first)element and p + 1 is a pointer to the next (third) element. Furthermore, given a, a + 2 is the address two elements from a and a + 3 is the address three elements from a. Given pointer, p, pn is a pointer to the value n elements away. memory Addresses p - 1 a a[0] 2 48682 4 48683 p a + 1 a[1] 48687 6 p + 1 a + 2 a[2] 8 48691 p + 2 a + 3 a[3] p + 3 a + 4 a[4] 48692 22 The meaning of adding or subtracting here is different from normal arithmetic. When you add an integer n to a pointer value, you will get a value that corresponds to another index location, n elements away. In other words, n is an offset from the original pointer. To determine the new value, C must know the size of one element. The size of the element is determined by the type of the pointer. This is one of the prime reasons that pointers of different types cannot be assigned to each other.
Pointers Pointer arithmetic allows us to assign an address of an array element to a pointer using the name of the array and the offset. p = a + 1; Second, we can use it with the indirection operator to access or change the value of the element we are pointing to. The two following expressions are exactly the same when a is the name of an array and n is an integer. *(a + n) is identical to a[n] memory Addresses or *(a + 0) a[0] 2 48682 4 48683 *(a + 1) a[1] or 48687 6 *(a + 2) or a[2] or 8 48691 *(a + 3) a[3] or *(a + 4) a[4] 48692 22