C Programming and Data Structures: Unit II: C Programming – Advanced Features

Pointers

Definition, Syntax, Advantages, Initializing, Example C programs

Pointers to Variables - Advantages of Pointers - Initialization - Accessing Variable through Pointer - Pointer Arithmetic

Pointers

AU: May-17, Marks 8

 

1. Pointers to Variables

Definition : Pointer is a variable that represents the memory location of some other variable. The purpose of pointer is to hold the memory location and not the actual value.

In C declaration if the variable is preceded by asterisk or then it is called pointer variable.

 

2. Advantages of Pointers

Following are some advantages of using pointer that illustrates its significance.

1. Pointers allow the dynamic memory management.

2. It helps to return more than one values from the function.

3. It allows to pass arrays, strings and structures efficiently.

4. It provides direct access to the memory.

5. It improves the execution speed of the program.

6. It reduces the storage space of the program.

7. Pointers help to build the complex data structures such as linked list, stack, queues, tree, graphs etc.

 

3. Initialization

Once the pointer variable is declared then it can be used further. In the sense we can assign some value to it. But note that the pointer variable is basically used to store some address of the variable which is holding some value.

Consider,

Line 1- > int *ptr;

Line 2- > int a,b;

Line 3- > a =10; /* storing some value in a*/

Line 4 - > ptr = &a;/*storing address of a in ptr*/

Line 5- > b=*ptr;/*getting value from address in ptr and storing it in b*/

Here we have used two important operators * and &. The * means 'contents at the

specified address' and & means the 'address at'.

On Line 1 and Line 2 we have declared the required variables out of which ptr is a pointer variable and variables a and b are our normal variables. On Line 3 we have assigned value 10 to variable a. The Line 4 tells us that address of variable a is stored in a pointer variable ptr. And on Line 4 we have written that in ptr variable we have stored some address and at that address whatever value is stored, store that value in variable b. That means at ptr we have stored address of variable a. Then at the address of a whatever is a value we have to store that value in variable b. This can be illustrated by following Fig. 2.5.1.


We can declare pointer variables of various types such as int, char, double etc.

Consider the declarations as given below -

int *iptr;

char *cptr;

float *fptr;

The iptr will store the address of a variable which is of type integer, similarly cptr will store the address of a variable which is of character type and so on.

Similarly we cannot initialize the pointer variable in this way-

iptr = 0XCF00; ……………….. is wrong

Similarly we cannot assign one variable of some data type to a pointer variable of different type

For example,

int *ptr;

float a,b;

a=3.14;

b=10.51;

ptr=&a; /*this is wrong*/

 

4. Accessing Variable through Pointer

To understand how to access the variables through pointer let us understand the program given below -

 

#include<stdio.h>

#include<conio.h>

void main( )

{

int *ptr;

int a,b;

clrscr();

a=10; /* storing some value in a*/

ptr=&a;/*storing address of a in ptr*/

b=*ptr;/*getting value at ptr in b*/

printf("\n a= %d", a);/*printing value stored at a*/

printf("\n ptr= %u",ptr);/*printing address stored at ptr*/

printf("\n ptr=%d", *ptr); /*Level of indirection at ptr*/

printf("\n b= %d",b);/*printing the value stored at b*/

getch();

}

Output

a= 10

ptr= 65524

ptr=10

b= 10

Program Explanation :

In above program, firstly we have stored 10 in variable a, then we have stored an address of variable a in variable ptr. For that we have declared ptr as pointer type. Then on the next line value at the address stored in ptr is 10 which is been transferred to variable b. Finally we have printed all these values by some printf statements.

The following program illustrates the concept of & and * in more detail

#include<stdio.h>

#include<conio.h>

void main()

{

int *ptr;

int a,b;

clrscr();

a=10;

b=20;

}

printf("\n Originally a=%d b=%d",a,b);

ptr=&a;

b=*ptr;

printf("\n\n Now the changed values are\n\t

a= %d, b=%d",a,b);

printf("\n ptr = %u",ptr);

printf("\n &ptr = %u", &ptr);

printf("\n *ptr = %d", *ptr);

printf("\n *(&ptr) = %u",*(&ptr));

printf("\n Address of a is &a= %u",&a);

printf("\n Address of b is &b = %u", &b);

getch();

}

Output

Originally a=10 b=20

Now the changed values are

a=10,b=10

ptr = 65522

&ptr = 65524

*ptr = 10

*(&ptr) = 65522

Address of a is &a= 65522

Address of b is &b = 65520

In above program there are 2 variables and 1 pointer variable. The values stored in these variables are - Refer Fig. 2.5.2.


Key Point: Whenever we want to store address of some variable into another variable, then another variable should be of pointer type.

 

Ex. 2.5.1

Given the following declaration :

int x = 10, y = 10;

int *p1 = Ɛx, *p2 = Ɛy;

What is the value of each of the following expressions?

1) (*p1)++

2) - - (*p2)

3) *p1 + (*p2)- -

4) ++(*p2) - *pl

5) *p1 + *p2

6) - (*p1) + *p2

Sol. :

1) (*p1) ++

Ans: 10

Explanation: First value at p1 is accessed through p1 and then value is incremented by 1. i.e. (11).

2) -- (*p2)

Ans : 9

Explanation: First value at (p2) is accessed then it is decremented by one (- -) and then printed as (- -) is used as predecrement operator.

3) *p1 + (* p2) -

Ans: Output 20

Explanation: Here value at p1 and value at p2 are added and then value at p2 is decremented by 1.

so* p2 = 9

4) ++ (*p2) - * p1

Ans: Output = 1

Explanation: Value at px is considered, then preincrement operator (++) is applied on that value i.e. (it will be 11) then value at p1 is considered and then substraction is performed.

5) *p1 + *p2ola

Ans. Output = 20

Value at p1 is added with value at p2.

6) - - (*p1) + *p2

Ans: Output = 19

Explanation: Value at pl is considered, then it is decremented by 1 and then value at p2 is added with the result.

 

Ex. 2.5.2 Explain the effect of the following statements:

i) int p, *p;

ii) int q, *p = Ɛ q;

iii) int (* p) ++;

iv) int p++;

v) char *p;

vi) int a = p+5; *

Sol. :

i) int p, *p: This statement will cause a compiler error for multiple declarations of variable p.

ii) int q, *p = & q: The variable p will act as an interger pointer and will hold the address of q. Hence the result of q and *p will be the same.

iii) int (* p) ++: The (*p)++ means increment the value of p by 1. But at the declaration, if we try to increment *p then it will generate syntax declaration error.

iv) int p + + : The p++ means increment the value of p by 1, but during declaration we cannot increment the value of variable. A declaration syntax error will be generated.

v) char *p;: The *p will be a character pointer that means it will store the address of character variable.

vi) int a = *p + 5; : If *p will store some value then variable a will store the value of *p + 5.

1) Due to use of pointers the execution of the programs become fast.

2) Pointers are used for dynamic memory allocation. We allocate a block of memory to an array and it can be accessed using a single pointer.

3) Functions can be handled using pointers.

4) Using pointers the wastage of memory can be avoided.

5) The pointer can be used as a scalar data type as well as the derived data type.

 

Ex. 2.5.3 Given the following declarations: int m = 50, n = 50, int *p1 = Ɛ m, *p2 = Ɛ n; What is the value of each of the following expressions?

i) (* p1) ++;

ii) -- (* p2);

iii) *p1 + (*p2) --;

iv) ++ (*p2) - *pl

 

i) (*p1) ++ gives 50:

Explanation: The value at pl is accessed first. The post increment operator is given. Hence value will be incremented latter.

 

ii) - - (*p2) gives 49

Explanation: The -- is a predecrement operator. Hence value at p2 i.e. 50 is decremented first and then displayed

 

iii) *p1 + (*p2) -- gives 100

Explanation: Here value at p1 and value at p2 are added and then decremented by 1.

 

iv) ++ (*p2) - *p1 gives 1

Explanation: The value at p2 is preincremented which becomes equal to 51 which value at p1 i.e. 50 is subtracted. Hence is the output.

 

5. Pointer Arithmetic

Basic Concept: Pointer arithmetic is a method of calculating the address of an object with the help of arithmetic operations on pointers.

Various operations can be performed using pointer variables as follows -

Let

int *ptr1,*ptr2;

int x;


But here is a list of some invalid operations. These operations are not allowed in any C program -


Now consider

int *ptr;

This is a pointer variable which is of integer type. This allocates the memory of 2 bytes for each such variable. If there are 10 integer pointers then total 20 bytes of memory block will be reserved.

Consider a block in memory consisting of ten integers in a row. That is, 20 bytes of memory are set aside to hold 10 integers.

Now, let's say we point our integer pointer ptr at the first of these integers. Furthermore lets say that integer is located at memory location 100 (decimal). What happens when we write :

ptr + 1;

it points to an integer it adds 2 to ptr instead of 1, so the pointer "points to" the next integer, at memory location 102. The same goes for other data types such as floats, doubles, or even user defined data types such as structures. This is obviously not the same kind of "addition" that we normally think of. In C it is referred to as addition using "pointer arithmetic".

The ptr++ or ++ptr is equivalent to ptr+1

As a block of 10 integers in a contiguous fashion is similar to the concept of array we will now discuss an interesting relationship between arrays and pointers.

Consider the following:

int my_array[ ] = {1,23,17,4,-5,100};

Here we have an array containing 6 integers. We refer to each of these integers with the help of subscript of my_array, i.e. using my_array[0] through my_array[5]. Alternatively, we can also access them via a pointer as follows:

int *ptr;

 /* point out pointer at the first integer in our array */

ptr = &my_array[0];

my_array


my_array [0] is 1 or it is (my_array + 0)

my_array [1] is 25 or it is (my_array + 1) ant

my_array [2] is - 17 (my_array + 2)

my_array [3] is 4 (my_array + 3)

my_array [4] is 45 (my_array + 4)

my_array [5] is 10 (my_array + 5)

Fig. 2.5.4 Method 1 for accessing elements of an array


ptr = & my_array [0] i.e. location 0th in array

then * ptr will contain 1 i.e. my-array [0] value

* (Ptr + 1)  a[1] i.e. 25

* (Ptr + 2) a[2] i.e. - 17

* (Ptr + 3) a[3] i.e. 4

*(Ptr + 4) a[4] i.e. 45

* (Ptr + 5) a[5] i.e. 10

Fig. 2.5.5 Method 2 for accessing array elements

then * ptr will contain 1 i.e. my_array [0] value

Thus there are two ways by which array element can be accessed -

1. Using the array subscript

2. Using the pointer to array

Then we can print all the elements of an array. This is illustrated by following program -

#include <stdio.h>

int my_array[] = {1,25,-17,4,45,10};

int *ptr;

int main(void)

{

int i;

ptr = &my_array[0]; /* point our pointer to the first element of the array */

printf("\n\n");

for (i = 0; i < 6; i++)

{

printf("\nUsing 1st Method: my_array[%d] = %d",i,my_array[i]); /*<-- A */

printf("\nUsing 2nd Method: ptr + %d %d\n",i,

*(ptr + i)); /* < -- B*/

}

return 0;

}

Compile and run the above program and carefully note lines A and B and that the program prints out the same values in either case. Also observe how we dereferenced our pointer in line B, i.e. we first added i to it and then dereferenced the new pointer. Thus the output will be -

Output

Using 1st Method: my_array[0] = 1

Using 2nd Method: ptr + 0 = 1

 

Using 1st Method: my_array[1] = 25

Using 2nd Method: ptr + 1 = 25

 

Using 1st Method: my_array[2] = - 17

Using 2nd Method: ptr + 2 = - 17.

 

Using 1st Method: my_array[3] = 4

Using 2nd Method: ptr + 3 = 4

 

Using 1st Method: my_array[4] = 45

Using 2nd Method: ptr + 4 = 45

 

Using 1st Method: my_array[5] = 10

Using 2nd Method: ptr + 5 = 10

Now, Change line B to:

printf("ptr + %d %d\n",i, *ptr++);

and run it again...you will get the same result.

Now, change it to :

printf("ptr + %d %d\n",i, *(++ptr));

Try once more. Each time try and predict the outcome and carefully look at the actual outcome. Again the same result will be achieved.

In C, instead of

ptr = &my_array[0];

we can write :

ptr = my_array;

to achieve the same result. This means that the name of an array is a pointer.

Key Point: "The name of the array is the address of first element in the array". Using pointer arithmetic (increment or decrement operator) we can access the subsequent elements of the array.

 

Ex. 2.5.4 Write a C program using pointer for searching the desired element from the array.

Sol. :

#include<stdio.h>

#include<conio.h>

void main( )

{

int a[10],i, n,*ptr,key;

clrscr( );

printf("\n How Many elements are there in an array?");

scanf("%d",&n);

printf("\n Enter the elements in an array");

for(i=0;i<n;i++)

scanf("%d",&a[i]);

ptr=&a[0];/*copying the base address in ptr */

printf("\n Enter the Key element");

scanf("%d", &key);

for(i=0;i<n;i++)

{

if(*ptr==key)

{

printf("\n The element is present");

break;

}

else

ptr++; /*pointing to next element in the array*/

/*Or write ptr=ptr+i*/

}

getch( );

}

Output

How many elements are there in an array?5

Enter the elements in an array

10

20

30

40

50

Enter the Key element40

The element is present

 

Ex. 2.5.5 Write a program using pointer to compute the sum of all elements stored in any array.

Sol. :

#include<stdio.h>

void main()

{

int a[ ]={10,20,30,40,50};

int sum=0;

int n=5;

for(int i=0;i<5;i++)

}

{

sum=sum+(*(a+i));

}

printf("%d", sum);

}

 

Ex. 2.5.6 If we declare an array a [i] [j] and p is pointer to first row find out

i) Pointer to ith row

ii) Pointer to first element in the ith row

iii) Pointer to jth element in ith the row

iv) Value store in the cell a [i][j]

Sol. :

i)

void main( )

{

int a[][3]={{10,20,30}, {40,50,60}};

int *ptr;

for(int j=0;j<3;j++)

{

ptr=&a[0][j];

printf("%d", *ptr);

}

}

ii)

void main( )

{

}

int a[][3]={{10,20,30}, {40,50,60}};

int *ptr;

ptr=&a[0][0];

printf("%d", *ptr);

}

iii)

void main( )

{

int a[3][3]={{10,20,30}, {40,50,60}};

int *ptr;

ptr=&a[1][2];

printf("%d", *ptr);

}

iv)

{

void main( )

{

int a[3][3]={{10,20,30}, {40,50,60}};

int *ptr;

for(int i=0;i<2;i++)

{

for(int j=0;j<3;j++)

{

ptr=&a[i][j];

printf("%d", *ptr);

}

printf("\n");

}

}

 

Ex. 2.5.7 Write the output for the following code:

1) int t[3][2][4]={2,4,3,6,1,6,7,9,8,2,1,1,2,3,7,3,1,6,2, 4,0,7,9,5};

printf("%d", *(*(*(t+2)+1)+3));

2) char *cp;

int *ip;

cp=(char *)0×100;

ip=(int *)cp;

ip++;

cp++;

printf("cp=%x ip=%x", cp, ip)'

Sol. :

1) The output is 5 because, the elements are arranged in two rows and four columns. And there will be 3 such blocks. The arrangement of elements will be


*(t + 2) = {{1, 6, 2, 4}, {0, 7, 9, 5}}

*(*(t + 2) + 1) = {0, 7, 9,.5}

*(*(*(t+2)+1)+3) = 5.

2) The address assigned to cp variable is 100. The same base address i.e. 100 is assigned to ip. The cp represents character pointer and ip represents interger pointer. The size of character variable is 1 byte and size of interger variable is 2 bytes.


Hence output is cp = 101 and ip = 102.

 

C Programming and Data Structures: Unit II: C Programming – Advanced Features : Tag: : Definition, Syntax, Advantages, Initializing, Example C programs - Pointers