Pointer in C Language

Pointer in C Language

Let us understand what are the pointers in C, the Pointer  operator (*) is used heavily in C Language and also  called “value at address“ operator, it is used to fetch the value stored at a particular address. The pointer operator is also known as indirection operator, and has just the inverse effect of & operator. Pointer in C Language can be demonstrated via a simple  C Program shown below.

#include<stdio.h>
void main()
{
    int x=5;
     printf (“%d %d” ,x, *&x) ;
}

gives the output: 5 5

because, the & operator creates reference and * operator de-references it. So, any sequence of * and & respectively ( e.g., *&*&*&*&*&x) can be applied any number of times to a variable.

Address operator (&)

Address operator, is used to evaluate the address of an  object. An  object can be anything from basic types of variables to the user-defined variables (defined using struct, union, enum, etc).  example below, demonstrates the address operator.

#include<stdio.h>
void main( )
 {
      int x=5;
     printf(“value of x = %d,  address of x  = %u” ,x, &x)  ;
}

It will print

Value of x=5, address of x=12345 (machine-dependent)                 x variable’s name

Pointer in C
Pointer in C

 The address of x is a machine-dependent value, It is the memory address of the location where x is stored in the memory. This address may differ from machine to machine, but you don’t have to worry about it as it is taken care by the compiler.  & operator is used to fetch the address of an object, and do any manipulations.

Pointer expressions in C

Let x be an int variable with value 5. The address of x is &x. We can store this address into some other variable, as the address of a memory location is a whole number. We store the address of x in a variable, say y, which is also of type int, then we can  write the following code.

     int x=5;

    int y=&x;

  In the above code, since y is a variable, so the compiler allocates the memory for it. But we cannot do much with the value stored in y (which is the address of x) except print it or display it. However, since y stores address, it must be declared in such a way that make it distinct from normal variables. Thus, we declare y as

int   *y;                              /* right way to declare a variable that stores address in it */

 as the address stored in y is an int . This  declaration tells the C compiler that y is going to store the address of an integer value, or simply y is going to point to an int. Thus, y is a pointer that points to an int type value. The following is the example of pointers in C:

#include<stdio.h>
{
   int x=5 ;
   int   *y;                   /* y is a pointer to int type value */ 
   y=&x:
   printf(“Address of x ( in 2 different ways ) : %u %u” ,&x, y) ;
   printf(“Address of y =%u  ,  value of y = %d” ,&y, y) ;
   printf(“ value of x” ( in 3 different ways) : %d  %d %d”,x,*y,*&x); 
}

Output

Address of x ( in 2 different ways)  :  65524    65524

Address of y = 65522 , value of y = 65524 65524                          65524

Value of x, (in 3 different ways)   :  5  5   5

Pointer in C
Pointer in C

What we have learnt so far is:

  • & is address operator, that gives the address of its operand.
  • * is an indirection operator, that gives the “value at the address stored in its operand” indirectly.
  • * operator is used to declare a pointer as shown below:

            Int *p;                /* p is a pointer to an int type value*/

Since a pointer is a variable, its address can also be stored in some another variable that will also be a pointer. So, its declaration would need two * operators ( to denote that it is pointer to a pointer). For example,

#include<stdio.h>
void main()
{ 
   int x=5;
    int *px=&x;
    int  * * ppx =&px;
    printf(“Address of x ( in 3 ways) = %u %u %u”,&x,px,*ppx) ;
    printf(“value of x ( in 4 ways) = %d %d %d” , x, *&x, *px, ** ppx) ;
}

The output of the above program will be clarified by the following memory diagrams :

Now, in the first print f statement, 

&x = address of x = 65524

Px = value at px = 65524

*ppx= value at address stored in ppx = value at address 65520 = 65524

So &x, px, and *ppx all print the addresses of x. Similarly,

X = value stored in x = 5

*&x = * (&x) = *(65524) = value at address 65524 =5

**ppx = * ( value at address stored  in ppx)  = * (value at 65522)

            =* (65524)  = value at address 65524 = 5

So x, * &x, *px and ** ppx all print the value stored in x.

What does the following declarations mean?

int  *i;

char *c;

float * f;

 The above declarations mean that i, c, and f are pointer variables, i.e. they are going to hold addresses. Since addresses are always whole numbers, pointers always contain whole numbers. The first declaration means that i is going to store the address of an integer value . The second declaration means that c is going to store the address of a character value. The third declaration means the f is going to store the address of a floating-point value.

Pointer Arithmetic in C

Since pointers are special type of variables (as they store addresses, and not values), all the arithmetic operators that can be applied on normal ( i.e. non – pointer) variables cannot be applied on pointers. That’s why they have a separate arithmetic, known as pointer arithmetic. We cannot apply division, multiplication or modulus operations on pointers, as they are meaningless

Arithmetic on pointers is limited to two operations

Addition

This operation too has its restrictions:

  • Two pointers cannot be added.
  • ++ operator can be applied on pointers, It takes pointer to the address of next location from the address that is currently stored in the pointer.
  • A constant integer n can be added to a pointer. “This gives the address of the location that is n*sizeof(pointer type) farther from the address currently stored in the pointer.
  • An integer variable can also be added to a pointer.

All the above points can be illustrated with the help of the following example:

Int *arr1={10,20,30,40,50} ;          /* first pointer*/

Int  *arr2= {10,20,30} ;  /* second pointer */

Int i;                             /* an integer variable*/

Arr1+=i;                                    /*legal, an integer variable can be added to a pointer*/

Arr1+=2;                                  /*legal, an integer constant can be added to a pointer */

Arr1++;                                    /*legal , ++ operator can be applied to a pointer*/

Arr1+=arr2;                                          /*illegal, arr1 pointes far beyond the limits of arr1 */

                                               /* that is why two pointers cannot be added. */

Subtraction

This operation too has its restrictions:

  • Two pointers can be subtracted.
  • –operator can be applied on pointers. It takes pointer to the address of previous location from the address that is currently stored in the pointer.
  • A constant integer n can be subtracted from a pointer. This gives the address of the location that is n* size of(pointer type) back from the address currently stored in the pointer.
  • An integer variable can also be subtracted from a pointer.

All the above points can be illustrated with the help of the following example:

int arr[10];

int i=2;

int*p=&arr[2];   /* p stores the address of 3rd element of the array arr */

    int *q=&arr[5];  /* q stores the address of 6th element of the array arr*/

      int *r=p+q;    /* illegal , two pointers cannot be added. r points far beyond the limits of the array arr*/

int *diff=q-p;                             /* legal, two pointers can be subtracted. Result is the

difference of their positions (5-2=3 here) irrespective of the size of the integer on a particular machine */

p — ;                                     /* legal, — operator gives address of previous location.

                                            /* so, here it gives the address of arr[1] */

p – = i ;              /* legal , an int variable can be subracted from a pointer*/

p – = 2;             /* legal, an int constant can be subtracted from a pointer */

Order of evaluation in pointer arithmetic

In pointer arithmetic, we frequently use the unary operators

+ + – * & –

When two or more of above unary operators appear together in an expression, then it is necessary to know the order in which they are evaluated because each of these unary operators have same precedence level and so they are evaluated from right to left. Their order can affect the total expression. For example, if ptr  is a pointer to an int type, then

++ptr or ptr++ points to the next location after ptr

-ptr or ptr-points to the location previous to ptr

Ptr+ i points to the location i* size of (int) forward from ptr

++*ptr or (*ptr) ++ increments value at address stored in ptr by 1

*ptr++ fetches the next value after the value stored at the address which is in ptr

Comparison of two pointers in C Language

Two pointers can be compared if both of them have the same data type. Such comparisons are useful when both the pointers point to the same object, such as a variable or an array.

Suppose px and py are two pointer that point to data items of x and y of the same type, then

px<py         is evaluated as TRUE if x is stored before y.

px>py         is evaluated as TRUE if x is stored after y.

px<=py      is evaluated as TRUE if x is stored before y, or px and py point to the same location.

Px>=py       is evaluated as TRUE if x is stored after y, or px and py point to the sam  e location.

Px==py       is evaluated as  TRUE if px and py point to same location.

Px!=py        is evaluated as TRUE if px and py point to different locations but are of the same type.

Px==NULL   is evaluated as TRUE if px is assigned a NULL    (0) value.

Passing references (addresses) to a function

We can pass arguments to a function in two ways:

  • Passing the values of the arguments
  • Passing the references (addresses) of the arguments

In the first method, the ‘value’ of each actual parameter in the calling function is copied to the corresponding formal parameter of the called function. So, when the changes are made to the formal parameters in the called function, there is no effect on the values of the corresponding actual parameters in the calling function.

      In the second method, the ‘address’ of each actual parameter in the calling function is copied to the corresponding formal parameter of the called function. Since address is passed, so any change made in the value of the formal parameter using this address, will also be reflected in the corresponding value of the actual parameter.

      Pointers are the best tool for passing the addresses (or, references) of the arguments in the calling function to the called function. This is shown below:

#include<stdio.h>
Void swap (int *x, int *y)    
{
    int z;
    z=*x;
    *x=*y;
   *y=z;
}
void main ()
{
     int a=5, b=10;
    printf(“Before calling swap () \n a=%d b=%d” ,a,b);
    swap(&a, &b);                 
    printf ( “After calling swap () /n  a =%d b=%d” ,a,b) ;
}

The output of the above program is,

Before calling swap (), a=5 b=10

After calling swap() , a=10 b=5

Returning more than one values from a function

We know that it is not possible to return more than one value at a time from a function. Pointers make it possible by the clever using of passing addresses to the function. Following is the program-proof of it.

#include<stdio.h>
void rect(float l, float b, float *a, float *p)
{
          *a=l*b;
         *p=2*(l+b);
}
void main()
{
       float length, breadth, area, perimeter;
       printf(“Enter the length and breadth of a rectangle:”);
       scanf(“%f %f”,&length,&breadth);
       rect(length, breadth, &area, &perimeter);
      printf(“ Area=%.2f Perimeter=%.2f\n”,area, perimeter);
}

Output:

Enter the length and breadth of a rectange: 2.5  3.2

Area=8.0 0  Perimeter=11.40

Pointers versus Arrays

Walking efficiently along arrays

The most frequent use of pointers in C is for walking efficiently along arrays. We know that in an array, the array name represents the address of the zeroth element of the array, so we can’t use it on the left side of an expression (Of course, we can’t change the address of something by assigning to it.) If we say

                     char *str;

                     char s [100] ;

str is of type pointer to character (although it doesn’t yet point anywhere). We can make str point to  an element of s by

str=&s[0] ;

    Or

str=s;

Since s is the address of the first element s[0] of the array s. Now

*str gives s [0].

*(str+1) gives s[1]

*(str+2) gives s[2]

*(str+i) gives s[i ]

And

str = s;          /* or, str=&s[] ; */

str++;

leaves str pointing at s[1].

Passing one-dimensional array of any length efficiently to a function.

Now we are going to use a pointer in a function, named len, that computes how long character array is. A character array is terminated with a ‘\0’. This function when defined using an array is:

int len(char s[])

{

    int count:

    for(count=0; s[count] !=’\0’ ; count++)

;                                       /*null statement*/

return (count) ;

}

Rewriting with pointers gives

int len (char *s)

{

     int count;

     for( count=0 ;*s !=’/0’ ; s++, count++)

    ; /* null statement */

    return (count);

}

Now calling the above function in main() is shown below:

main()

{

    char str[9] =”RAMAYANA” ;

   printf ( “The length of the string  %s is %d”, str, len(str) ) ;

}

This program can be well explained using memory diagram of the string (“Ramayana”) , as is shown below:

R A M A Y A N A \0
1234 1235 1236 1237 1238 1239 1240 1241 1242

 

Where 1234,1235,…,1242 are assumed addresses where the characters of the string “RAMAYANA” are stored. Now, the argument  char *s in the function len shows that it is meant for accepting an address. We give it the starting address of the character array (or string) str, which is &str [ 0 ] or simply str. Suppose this address is1234. This address 1234 is received by  the pointer argument s in the function len. Now in the body of the function len, what happens is that

In the start:

                  Count = 0

                  S = 1234

                  *s = value at address 1234 = R (see the memory diagram of the string “RAMAYANA”) now, the condition (*s!=’\0’)  is checked, which is true (as  * s= ‘R’) so, address s and counter count both are incremented by 1  (by expressions: s++,  count++), so that now

                  Count=1

                  S=1235

                  *s=value at  address 1235 = ‘A’ (see the memory diagram of the string “RAMAYANA”)

Similarly by incrementing the address s, and counter count, and checking the condition (*s!=’\0’), we reach at the end of the string, where s =1242 (according to the above diagram). At this stage, we have  count =*. Now the condition (*s!=’\0′) becomes false, and the for loop is terminated. Thus we get the length of the string RAMAYANA as 8.

I have tried to explain the pointers in C comprehensively, If you have questions please do comment.

Similar Posts:

Functions          Control Structures in C                    Arrays in C

You May Also Like:

What is New in HTML5        JavaScript Functions and Loops          How to Activate GST in Tally.ERP9 ?

To Download Official TurboC Compiler from here

 

5 1 vote
Article Rating
Subscribe
Notify of
guest

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback
3 years ago

[…] Pointer in C Language                          Functions                            Arrays in C […]

trackback
3 years ago

[…] Pointer in C Language […]

trackback
3 years ago

[…] Pointer in C Language […]

Please Subscribe to Stay Connected

You have successfully subscribed to the newsletter

There was an error while trying to send your request. Please try again.

DigitalSanjiv will use the information you provide on this form to be in touch with you and to provide updates and marketing.
Share via
Copy link
Powered by Social Snap