Professional Documents
Culture Documents
Unit IV
Pointers
A pointer is a memory variable that stores a memory address. Pointer can have any name that is legal fro other variable and it is declared in the same fashion like other variables but it is always denoted by
* operator.
Features
1. Pointers save the memory space. 2. Execution time with pointer is faster because data is manipulated with the address i.e. direct access to memory location. 3. Pointers reduce the length and complexity of a program. 4. The memory is accessed efficiently with the pointers. The pointer assigns the memory space and it also releases. Dynamically memory is allocated. 5. Pointers are used with data structures. They are useful for representing tow-dimensional and multi dimensional arrays, structures.
Pointer Declaration
The declaration of pointer is as follows data type *pt_name; This tells the compiler three things about the variable pt_name 1. The asterisk (*) tells that the variable pt_name is a pointer variable. 2. pt_name needs a memory location. 3. pt_name points to variable of type data type Example: int *p; In the above example, the variable p as a pointer variable that points to an integer data type. Remember that the type int refers to the data type of the variable being pointed to by p and not the type of the value of the pointer. Similarly, the following declares character and floating pointers. char *ch; float *x; Once the pointer variable is declared, it can be made to a point to a variable using an assignment statement.
Page 1
N.Vamshi Krishna
Unit IV
Initializing a Pointer
After declaration of pointer, it can be initialized with an address of another variable. The assignment statement is as follows int *p, a; p = &a; In the above statements, a is an integer variable. p is a integer pointing variable.i.e. &a gets the address of variable a and assigns to the pointer variable p.
Page 2
N.Vamshi Krishna
Computer Programming and Data Structures Technology Address of pointer = 65520 Value of y = 10
Unit IV
Page 3
N.Vamshi Krishna
Unit IV
/*Program to find smallest of two numbers using function returning pointers*/ int* smaller(int* , int*); void main() { int a,b,*p; printf(Enter values of a and b :); scanf(%d%d,&a,&b); p = smaller(&a, &b); printf(Smaller number = %d,*p); } int* smaller(int* px, int* py) { return ( *px < *py ? px : py); } Output : Enter values of a and b : 67 89 Smallest number = 67
Pointers to Pointers
A pointer to a pointer in C can be used to indirectly point to the memory address of a variable. A pointer is a variable that contains the address of another variable. As a result, pointer to pointer contains the memory address of a pointer, which holds the memory address of a variable. The declaration is done as follows Data type **pointer name Ex : int **ptr;*p, a=10; p = &a; ptr = &p; In the above example, a is a normal variable storing the value 10. p is a pointer variable which stores the address of a and ptr is the pointer to pointer which stores the address of pointer p. /*Program to demonstrate the usage of pointers to pointers*/ #include<stdio.h> void main() { int a=10,*ptr1,**ptr2; clrscr(); ptr1 = &a; ptr2 = &ptr1; printf("\na= %d",a); printf("\n&a = %u",&a); printf("\nptr1 = %u",ptr1); printf("\n*ptr1 = %d",*ptr1); printf("\n&ptr1 = %u",&ptr1); printf("\nptr2 = %u",ptr2); printf("\n*ptr2 = %u",*ptr2); printf("\n**ptr2 = %d",**ptr2); getch(); } Output a = 10 &a = 65524 ptr1 = 65524 *ptr1 = 10
I YEAR B.TECH CSE
Page 4
N.Vamshi Krishna
Unit IV
Compatibility
Pointers have a type associated with them. They are no just pointer types, but rather are pointers to a specific type. Each pointer therefore takes on the attributes of the type to which it refers in addition to its own attributes. Pointer Size Compatibility The size of all pointers is the same. Every pointer variable holds the address of one memory location in the computer. The size of the variable that the pointer references can be different; it takes the attributes of the type being referenced. All computers today have more than 65,535 bytes, which is the maximum address that could be stored in 2 bytes. So pointers size is 2 bytes in this case. Dereference Type Compatibility The deference type is the type of the variable that the pointer is referencing. With one exception, it is invalid to assign a pointer of one type to a pointer of another type, even thought he values in both cases are memory addresses and would therefore seem to be fully compatible. Although addresses may be compatible because they are drawn from the same set, what is not compatible is the underlying data type of the referencing object. In C we cant use the assignment operator with pointers to different types. If we try to, we get compile error. Ex: A pointer to char is only compatible with pointer to char and a pointer to an int is only compatible with pointer to int. We cannot assign a pointer to a char to a pointer to an int. A pointer to void is a generic type that is not associated with a reference type; that is, it is not the address of a character, an integer, a real or any other type. So, it is compatible for assignment purpose only with all the other pointer types. Thus, a pointer of any reference type can be assigned to a pointer to void type and a pointer to void pointer can be assigned to pointer of any reference type. Ex : void* ptr; Casting Pointers The problem of type incompatibility can be solved using casing. We can make an explicit assignment between incompatible pointer types by using a cast, just as we can cast int to char. Another use of the cast is to provide a type for void pointer. When we cast it, however, we provide the type. Ex: void* ptr; char* cptr; int* iptr; ptr = cptr; iptr = ptr; iptr = (int*) cptr;
Page 5
N.Vamshi Krishna
Unit IV
Note : Compatibility also includes dereference level compatibility. Ex: a pointer to int is not compatible with a pointerto-pointer to int.
Pointer Expressions
Like other variables pointer variables can also be used in expressions. If p1 and p2 are properly declared and initialized pointers, then the following expressions are valid *p1 * *p2 *p1 / *p2
*p1 > *p2
(Performs multiplication of values accessed by pointer variables) (Performs division of values accessed by pointer variables)
(Checks whether the first value accessed is greater than second variable accessed) etc.
/*Program to demonstrate pointers and expressions*/ #include <stdio.h> void main() { int a=12, b=4, *p1, *p2; clrscr(); p1=&a; p2=&b; printf(" *p1 + *p2 = %d",*p1+*p2); printf("\n*p1 - *p2 = %d",*p1-*p2); printf("\n*p1 * *p2 = %d",*p1* *p2); printf("\n*p1/*p2 = %d",*p1/ *p2); if(*p1 > *p2) printf("\n*p1=%d value is greater",*p1); else printf("\n*p2=%d value is greater",*p2); getch(); } Output *p1 + * p2 = 16 *p1 - *p2 = 8 *p1 * *p2 = 48 *p1 / *p2 = 3 *p1 =12 is greater
Page 6
N.Vamshi Krishna
Unit IV
When we declare an array, the compiler allocates a base address and sufficient amount of storage to contain all the elements of the array in the contiguous memory locations. The base address is the location of first element (index 0) of an array. The compiler also defines the array name as a constant pointer to first element. For example if we consider int x[10]; here, x is an integer array. The base address will be the address of x[0]. As per the compiler the name x is defined as constant pointer pointing to the first element x[0] and therefore x = &x; If we declare a pointer p as an integer pointer, then we can make the pointer p to point to array x by the following statement int x[10], *p; p = x; (this is equivalent to p = &x[0]); p = &x[0] (=6500) Now we can access every value of x by using p++ to move from one element to another . Like p+1 = &x[1] (=6502) p+2 = &x[2] (=6504) Instead of using array indexing, we can use pointers to access array elements. *(p+2) gives the value stored in x[2].. The pointer accessing method is much faster than array indexing. It is possible to avoid the loop control variable i as shown below p = x; while (p <= p+4) { Sum = sum + *p; p++; } We know that in one dimensional array x, the expression x[i] is equivalent to *(p+i) Pointers can be used to manipulate two-dimensional arrays as well. x[i][j] is represented as *(*(p+i)+j) The base address of the array &x[0][0] , the compiler allocates contiguous space for all elements row-wise. /*Program to demonstrate pointer and arrays */ #include<stdio.h> void main() { int a[5], *p, sum=0, i; clrscr(); p=a; printf("Enter 5 numbers :"); for(i=0; i<5; i++) { scanf("%d",p+i); sum = sum + *(p+i); } printf("Sum = %d", sum); getch(); } Output
I YEAR B.TECH CSE
Page 7
N.Vamshi Krishna
Unit IV
Passing an array to a function The name of an array is actually a pointer to the first element, so in a function call sending an array we send array name instead of address for processing. When we pass the array, we do not use the address operator. Remember, the array name is pointer constant, so the name is already the address of the first element in array Ex : int doIt(int[]); void main() { int arrName[100]; ---------; doIt(arrName); } int doIt(int* arrSalary) { ------------; }
Main
Page 8
N.Vamshi Krishna
Unit IV
Heap Data Memory Conceptual View of Memory
Global
Stack
Static Memory Allocation Static memory allocation requires that the declaration and definition of memory be fully specified in the source program. The number of bytes reserved cannot be changed during run time. This is the technique we have used to this point to define variables, arrays, pointers, and streams. Dynamic Memory Allocation Dynamic memory allocation uses predefined functions to allocate and release memory for data while the program is running. It effectively postpones the data definition, but not the data declaration, to run time. Memory Allocation Functions Four memory management functions are used with dynamic memory. They are malloc, calloc, realloc and free. First three are used for memory allocation and fourth is used for return memory when it is no longer needed. All the memory management functions are found in the standard library file stdlib.h. Block Memory Allocation (malloc) The malloc function allocates a block of memory that contains the number of bytes specified in its parameters. It returns a void pointer to the first byte of the allocated memory. The allocated memory is not initialized. Function prototype is void* malloc(size_t size); The type, size_t is defined in several header files including stdio.h. The type is usually an unsigned integer. To provide portability, the size specification in mallocs actual parameter is generally computed using the sizeof operator. For example, if we want to allocate an integer in the heap, then we call as follows pInt = malloc(sizeof(int)); malloc function returns the address of the first byte in the memory space allocated. If it is not successful, it return NULL pointer. An attempt to allocate memory from the heap when the memory is insufficient is known as overflow. It is up to the program to check for memory overflow. If it doesnt the program produces the invalid results or aborts with an invalid address the first time the pointer is used. If we call malloc with a zero size, the results are unpredictable. It may return NULL pointer or it may return some other implementation dependent value. Note : Never call malloc with a zero size
Page 9
N.Vamshi Krishna
Unit IV
Prior to C99, it was necessary to cast the pointer returned from a memory allocation function. The casting format is pointer = (type*) malloc(size); Ex: pInt = (int*)malloc(4);
Contiguous Memory Allocation (calloc) calloc is primarily used to allocate memory for arrays. It differs from malloc only in that it sets memory to null characters. The declaration is as follows void *calloc(size_t element_count, size_t element_size); Example : ptr = (int*) calloc(200, sizeof(int)); Reallocation of memory (realloc) It is highly efficient function. When given a memory pointer to a previously allocated block of memory, realloc changes the size of the block by deleting or extending the memory at the end of block. If the memory cannot be extended because of other allocations, realloc allocates a completely new block, copies the existing memory allocation to the new allocation and deletes the old allocation. The declaration is as follows void *realloc(void* ptr, size_t newSize); Example ptr = realloc(ptr, 15*sizeof(int)); Releasing Memory (free) When memory locations allocated by malloc, calloc or realloc are no longer needed, they should be freed using predefined function free. It is an error to free memory with a null pointer, a pointer to other than the first element of an allocated bloc, a pointer that is a different type than the pointer that allocated the memory, it is also a potential error to refer to memory after it has been released. The function declaration is void free(void* ptr); Example free(ptr); Releasing memory does no change the value in the pointer. It still contains the address in the heap. It is logic error to use the pointer after memory has been released. Note : The pointer used to free memory must be of the same type as the pointer used to allocate memory.
Array of Pointers
Array of pointers is especially helpful when the number of elements in the array is variable. Consider the following two dimensional array 32 13 22
I YEAR B.TECH CSE
18 11
12 16
24 12 42 19 14
Page 10
N.Vamshi Krishna
Unit IV
13 11
13 18
14
If we use two-dimensional array for storing these numbers, we are wasting a lot of memory. This array is also known as ragged array. The solution in this case is to create five one-dimensional arrays that are joined through an array of pointers. One implementation is as follows
int** table; table = (int**) calloc(rowNum+1, sizeof(int)); table[0] = (int*) calloc (4, sizeof(int)); table[1] = (int*) calloc (7, sizeof(int)); table[2] = (int*) calloc (1, sizeof(int)); table[3] = (int*) calloc (3, sizeof(int)); table[4] = (int*) calloc (2, sizeof(int)); table[5] = NULL;
Page 11
N.Vamshi Krishna
Unit IV
The above statement declares p1 as a pointer to a function and mul as a function and then make p1 to point to the function mul.
Page 12
N.Vamshi Krishna
Unit IV
Strings
Page 13
N.Vamshi Krishna