Beruflich Dokumente
Kultur Dokumente
UNIT-III (POINTERS)
POINTERS :
One of the powerful features of C is ability to access the memory variables by
their memory address. This can be done by using Pointers. The real power of C lies in
the proper use of Pointers.
A pointer is a variable that can store an address of a variable (i.e., 112300).We say
that a pointer points to a variable that is stored at that address. A pointer itself usually
occupies 4 bytes of memory (then it can address cells from 0 to 232-1).
Advantages of Pointers :
A pointer enables us to access a variable that is defined out side the function.
Pointers are more efficient in handling the data tables.
Pointers reduce the length and complexity of a program.
They increase the execution speed.
Definition :
A variable that holds a physical memory address is called a pointer variable or
Pointer.
Declaration :
Datatype * Variable-name;
int i,*p;
Consider the Statement
p=&i;
Here ‘&’ is called address of a variable.
‘p’ contains the address of a variable i.
The operator & returns the memory address of variable on which it is operated,
this is called Referencing.
The * operator is called an indirection operator or dereferencing operator which
is used to display the contents of the Pointer Variable.
int *p,x;
x =5;
p= &x;
Output
The Value of x is 5
The Address of x is 2000
The Address of x is 2000
The Value of x is 5
The Value of x is 5
USAGE OF POINTERS:
Pointers are an extremely powerful programming tool. They can make some things much
easier, help improve your program's efficiency, and even allow you to handle unlimited
amounts of data.
Pointers are used (in the C language) in three different ways:
1. To create dynamic data structures.
2. To pass and handle variable parameters passed to functions.
3. To access information stored in arrays. (Especially if you work with links).
4. Pointers are also used by experienced programmers to make the code more efficient
and thus faster.
POINTERS TO POINTERS :
So far, all pointers have been pointing directely to data. It is possible and with
advanced data structures often necessary to use pointers to that point to other pointers.
For example,we can have a pointer pointing to a pointer to an integer.This two level
indirection is seen as below:
//Local declarations
int a;
int* p;
int **q;
q p a
Ex: 234560 287650 58
//statements
In the above figure to refer to ‘a’ using the pointer ‘p’, we have to dereference it as
shown below.
*p
To refer to the variable ‘a’ using the pointer ‘q’ ,we have to dereference it twice to get to the
integer ‘a’ because there are two levels of indirection(pointers) involved. If we dereference it
only once we are referring ‘p’ which is a pointer to an integer .Another way to say this is that
‘q’ is a pointer to a pointer to an integer.The doule dereference is shown below:
**q
In above example all the three references in the printf statement refer to the variable ‘a’.
The first printf statement prints the value of the variable ‘a’ directly, second uses the pointer
‘p’, third uses the pointer ‘q’. The result is the value 58 printed 3 times as below
58 58 58
Pointer Expressions:
We can perform arithmetic operations on pointer variable just as you can a numeric value. As
we know that, a pointer in C is a variable which is used to store the memory address which is
a numeric value. The arithmetic operations on pointer variable effects the memory address
pointed by pointer.
Let ptr be an integer pointer which points to the memory location 5000 and size of an integer
variable is 32-bit(4 bytes). Now, when we increment pointer ptr
ptr++;
This is a very important feature of pointer arithmetic operations which we will use in
array traversal using pointers.
Decrementing a Pointer:
Similarly, Decrementing a pointer will decrease its value by the number of bytes of its data
type. Hence, after
ptr--;
ptr will point to 4996.
ptr--; is equivalent to ptr - (sizeof(pointer_data_type)).
Subtracting Pointers
The difference between two pointer returns indicates “How apart the two Pointers are. It
gives the total number of elements between two pointers.
For example, Let size of integer is 4 bytes. If an integer pointer 'ptr1' points at memory
location 10000 and integer pointer 'ptr' points at memory location 10008, the result of ptr2 -
ptr1 is 2.
void main() {
int int_var = 10, *int_ptr;
char char_var = 'A', *char_ptr;
float float_val = 4.65, *float_ptr;
/* Initialize pointers */
int_ptr = &int_var;
char_ptr = &char_var;
float_ptr = &float_val;
/* Incrementing pointers */
int_ptr++;
char_ptr++;
float_ptr++;
printf("After increment address in int_ptr = %u\n", int_ptr);
printf("After increment address in char_ptr = %u\n", char_ptr);
printf("After increment address in float_ptr = %u\n\n", float_ptr);
/* Adding 2 to pointers */
int_ptr = int_ptr + 2;
char_ptr = char_ptr + 2;
float_ptr = float_ptr + 2;
getch();
return 0;
}
Output
Address of int_var = 2293300
Address of char_var = 2293299
Address of float_var = 2293292
Now both a and a[0] points to location 2000. If we declare p as an integer pointer, then
we can make the pointer P to point to the array a by following assignment
P = a;
We can access every value of array a by moving P from one element to another.
i.e., P points to 0th element
P+1 points to 1st element
P+2 points to 2nd element
P+3 points to 3rd element
P +4 points to 4th element
Example: Program to find the sum of six numbers with arrays and pointers
#include <stdio.h>
int main()
{
int i, a[6],sum = 0;
printf("Enter 6 numbers:\n");
for(i = 0; i < 6; ++i)
{
// (a + i) is equivalent to &a[i]
scanf("%d",(a + i));
// *(a + i) is equivalent to a[i]
sum += *(a + i);
}
printf("Sum = %d", sum);
return 0;
}
Output
Enter 6 numbers:
2
3
4
5
3
4
Sum = 21
Arrays of Pointers:
There may be a situation when we want to maintain an array, which can store pointers to an
int or char or any other data type available. Following is the declaration of an array of
pointers to an integer:
datatype (*pointer_variable)[size];
For example
int (*ptr)[10]; ,Here ptr is a pointer that can point to an array of 10 integers, where we can
initialize ptr with the base address of the array then by incre menting the value of ptr we can
access different elements of array a[].
Alternatively we can initialise the names array as shown in the following programs:
#include< stdio.h>
void main(void)
{
char *names[2] = {"Frans", "Coenen"};
/* Output */
printf("names = %s, %s\n",names[0],names[1]);
/* New assignments */
names[0] = "Ray";
names[1] = "Paton";
/* Output */
printf("names = %s, %s\n",names[0],names[1]);
}
In the above the declaration of names both creates an array of pointers and initilises
the pointers with appropriate addresses. Once addresses have been assigned to the pointers,
each pointer can be used to access its corresponding string. The output from the above is as
follows:
You can also use an array of pointers to character to store a list of strings as
#include <stdio.h>
const int MAX = 4;
int main ()
{
char *names[] = {"Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali"};
int i = 0;
for ( i = 0; i < MAX; i++)
{
printf("Value of names[%d] = %s\n", i, names[i] );
}
return 0;
}
When the above code is compiled and executed, it produces the following
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
#include <stdio.h>
void swap(int,int);
main()
{
int a,b;
printf(“Enter the Values of a and b:”);
scanf(“%d%d”,&a,&b);
printf(“Before Swapping \n”);
printf(“a = %d \t b = %d”, a,b);
swap(a,b);
printf(“After Swapping \n”);
printf(“a = %d \t b = %d”, a,b);
#include<stdio.h>
main()
{
int a=10,b=20;
swap (&a, &b);
printf(“After Swapping \n”);
printf(“a = %d \t b = %d”, a,b);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
NULL Pointers:
It is always a good practice to assign a NULL value to a pointer variable in case you do not
have an exact address to be assigned. This is done at the time of variable declaration. A
pointer that is assigned NULL is called a null pointer.
The NULL pointer is a constant with a value of zero defined in several standard libraries.
Consider the following program −
#include <stdio.h>
int main ()
{
int *ptr = NULL;
printf("The value of ptr is : %x\n", ptr );
return 0;
}
When the above code is compiled and executed, it produces the following result −
The value of ptr is 0
Declaration :
Void * pointer_name;
When a pointer variable is declared using keyword void – it becomes a general purpose
pointer variable. Address of any variable of any data type (char, int, float etc.)can be assigned
to a void pointer variable.
We have seen about dereferencing a pointer variable in our article – Introduction to pointers
in C. We use the indirection operator * to serve the purpose. But in the case of a void pointer
we need to typecast the pointer variable to dereference it. This is because a void pointer has
no data type associated with it. There is no way the compiler can know (or guess?) what type
of data is pointed to by the void pointer. So to take the data pointed to by a void pointer we
typecast it with the correct type of the data holded inside the void pointers location.
Example program:-
#include
void main()
{
int a=10;
float b=35.75;
void *ptr; // Declaring a void pointer
ptr=&a; // Assigning address of integer to void pointer.
printf("The value of integer variable is= %d",*( (int*) ptr) );// (int*)ptr - is used for type
casting. Where as *((int*)ptr) dereferences the typecasted void pointer variable.
ptr=&b; // Assigning address of float to void pointer.
printf("The value of float variable is= %f",*( (float*) ptr) ); );// (float*)ptr - is used for type
casting. Where as *((float*)ptr) dereferences the typecasted void pointer variable.
}
The output:-
The value of integer variable is= 10
The value of float variable is= 37.75
Functions as pointers
• Function code is stored in memory
• Start of the function code or the address of a function is a “function pointer”
• Function pointer is “different” from other pointers since you do not allocate or deallocate
memory with them
• Function pointers can be passed as arguments to other functions or return from functions
Why use function pointers?
• Efficiency
• Elegance
• Runtime binding
Example:
int (*fn)(int,int) ;
Here we define a function pointer fn, that can be initialized to any function that takes two
integer arguments and return an integer. Here is an example of such a function
int sum(int x, int y)
{
return (x+y);
}
Now to initialize fn to the address of the sum, we can do the following.
fn = &sum /* make fn points to the address of sum */
or simply
fn = sum; /* just ignore the & . Function names are just like array names they are
pointers to the structure they are referring to */
So we use the sum function in two ways.
int x = sum(10,12); /* direct call to the function */
or int x = (*fn)(12,10); /* call to the function through a pointer */
#include<stdio.h>
int sum (int num1, int num2)
{
return sum1+sum2;
}
int main()
{
int (*f2p) (int, int);
f2p = sum;
int op1 = f2p (10, 13);
int op2 = sum (10, 13);
return 0;
}
Output:
Pointers to structure :
Structures can be created and accessed using pointers. A pointer variable of a structure can be
created as below:
struct name
{
member1;
member2;
--------
};
int main()
{
struct name *ptr;
}
In this program, “record1” is normal structure variable and “ptr” is pointer structure variable.
As you know, Dot(.) operator is used to access the data using normal structure variable and
arrow() is used to access data using pointer variable.
#include <stdio.h>
#include <string.h>
struct student
{
int id;
char name[30];
float percentage;
};
void main()
{
int i;
struct student record1 = {1, "Raju", 90.5};
struct student *ptr;
ptr = &record1;
printf("Records of STUDENT1: \n");
printf(" Id is: %d \n", ptrid);
printf(" Name is: %s \n", ptrname);
printf(" Percentage is: %f \n\n", ptrpercentage);
}
Output:
Records of STUDENT1:
Id is: 1
Name is: Raju
Percentage is: 90.500000
int main()
{
struct student record;
record.id=1;
strcpy(record.name, "Raju");
record.percentage = 86.5;
func(record);
return 0;
}
OUTPUT:
Id is: 1
Name is: Raju
Percentage is: 86.500000
int main()
{
struct student record;
record.id=1;
strcpy(record.name, "Raju");
record.percentage = 86.5;
func(&record);
return 0;
}
void structure_demo();
void structure_demo()
{
printf(" Id is: %d \n", record.id);
printf(" Name is: %s \n", record.name);
printf(" Percentage is: %f \n", record.percentage);
}
Output:
Id is: 1
Name is: Raju
Percentage is: 86.500000
struct name
{
member 1;
member 2;
...
struct name *pointer;
};
Example:
struct node
{
int info;
struct node *link;
};
The above illustrated structure prototype describes one node that comprises of two
logical segments. One of them stores data/information and the other one is a pointer
indicating where the link component can be found. .Several such inter-connected nodes create
a chain of structures.
The following figure depicts the composition of such a node. The figure is a
simplified illustration of nodes that collectively form a chain of structures or linked list.
Such self-referential structures are very useful in applications that involve linked data
structures, such as lists and trees. Unlike a static data structure such as array where the
number of elements that can be inserted in the array is limited by the size of the array, a self-
referential structure can dynamically be expanded or contracted. Operations like insertion or
deletion of nodes in a self- referential structure involve simple and straight forward alteration
of pointers.
Memory size can’t be modified while Memory size can be modified while
execution. execution.
Example: array Example: Linked list
1.Malloc()
By using malloc() we can create the memory dynamically at initial stage.
Malloc() required one argument of type size type that is data type size malloc() will
creates the memory in bytes format.
Malloc() through created memory initial value is garbage.
Syntax:
Void *p=(data type *)malloc(n * sizeof(data type));
Note: Dynamic memory allocation related function can be applied for any data type that's
why dynamic memory allocation related functions return void*.
When we are working with dynamic memory allocation type specification will be available at
the time of execution that's why we required to use type casting process.
Example:
int *ptr;
ptr=(int*)malloc(sizeof (int)); //2 byte
char*cptr;
cptr=(char*)malloc(sizeof(char)); //1 byte
/*C program to read a one dimensional array, print sum of all elements along with inputted
array elements using Malloc Memory Allocation.*/
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *arr;
int n,i;
int sum=0;
printf("Enter total number of elements: ");
scanf("%d",&n);
arr=(int*)malloc(n*sizeof(int)); /*allocate memory for limit elements dynamically*/
if(arr==NULL)
{
printf("Insufficient Memory, Exiting... \n");
return 0;
}
printf("Enter %d elements:\n",n);
for(i=0; i<n; i++)
{
printf("Enter element %3d: ",i+1);
scanf("%d",(arr+i));
sum=sum + *(arr+i); /*calculate sum*/
2.Calloc()
calloc() required 2 arguments of type count, size-type.
Count will provide number of elements; size-type is data type size.
calloc() will creates the memory in blocks format.
Initial value of the memory is zero.
Syntax:
Void *p=(data type *)calloc(n,sizeof(data type));
Int *arr;
arr=(int*)calloc(10, sizeof(int)); // 20 byte
char *str;
str=(char*)calloc(50, siceof(char)); // 50 byte
/*C program to read a one dimensional array, print sum of all elements along with inputted
array elements using Calloc Memory Allocation.*/
#include <stdio.h>
#include <stdlib.h>
void main()
{
int *arr;
int n,i;
int sum=0;
printf("Enter total number of elements: ");
scanf("%d",&n);
arr=(int*)calloc(n,sizeof(int)); /*allocate memory for limit elements dynamically*/
if(arr==NULL)
{
printf("Insufficient Memory, Exiting... \n");
return 0; }
printf("Enter %d elements:\n",n);
for(i=0; i<n; i++)
{
printf("Enter element %3d: ",i+1);
scanf("%d",(arr+i));
sum=sum + *(arr+i); /*calculate sum*/
3.Realloc():
By using realloc() we can create the memory dynamically at middle stage.
Generally by using realloc() we can reallocation the memory.
Realloc() required 2 arguments of type void*, size_type.
Void* will indicates previous block base address, size-type is data type size.
Realloc() will creates the memory in bytes format and initial value is garbage.
Syntax
4.free():
When we are working with dynamic memory allocation memory will created in heap
area of data segment.
When we are working with dynamic memory allocation related memory it is a
permanent memory if we are not de-allocated that's why when we are working with
dynamic memory allocation related program, then always recommended to deleted
the memory at the end of the program.
By using free(0 dynamic allocation memory can be de-allocated.
free() requires one arguments of type void*.
Syntax
void free(voie*);
int *arr;
arr=(int*)calloc(10,sizeof(int));
...
......
free(arr);
malloc () doesn’t initializes the allocated calloc () initializes the allocated memory to
memory. It contains garbage values zero