This blog is under construction
Showing posts with label pointers. Show all posts
Showing posts with label pointers. Show all posts

Thursday, 26 December 2013

Pointer to two dimensional array

If a pointer holds reference to an array, then it is called pointer to an array or array pointer.

How to declare pointer to an array?
int (*ptr)[3][3];
Here, ptr is the pointer to 2d array.

Let us see how to access array elements using pointer to a two dimensional array.


  #include <stdio.h>
  int main() {
        int i, j;
        /* arr is 3 X 3 array */
        int arr[3][3] = {10, 20, 30,
                         40, 50, 60,
                         70, 80, 90};
        int (*ptr)[3][3]; // pointer to 2d array

        /* assigning reference */
        ptr = &arr;

        /* accessing 2d array elements using pointers */
        for (i = 0; i < 3; i++) {
                for (j = 0; j < 3; j++) {
                        printf("%d ", *(*((*ptr) + i) + j));
                }
                printf("\n");
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~$ ./a.out
  10 20 30 
  40 50 60 
  70 80 90 


Wednesday, 25 December 2013

Array of pointer to integer

Array of integer pointers in nothing but an array whose elements are pointer to integer.

How to declare array of pointer to integer?
Below is the declaration for array of pointer to integer.
int *arr[10];

Dynamic memory allocation for integer pointers in an array:
Below is the procedure to perform dynamic memory allocation for the integer pointers in an array.
int *arr[3];
for (i = 0; i < 3; i++) {
    // allocate memory block to hold 3 integers
arr[i] = (int *)malloc(sizeof(int) * 3);
}

Example program on array of pointer to integer:
Let us see how to access elements pointed by integer pointers in an array using an example program.


  #include <stdio.h>
  #include <stdlib.h>
  int main() {
        int i, j, k, *arr[3];

        /* dynamic memory allocation for array of int pointers */
        for (i = 0; i < 3; i++) {
                arr[i] = (int *)malloc(sizeof(int) * 3);
        }

        /* assigning values to pointees */
        k = 0;
        for (i = 0; i < 3; i++) {
                for (j = 0; j < 3; j++) {
                        *(arr[i] + j) = k++;
                }
        }

        /* printing the values of pointees */
        for (i = 0; i < 3; i++) {
                for (j = 0; j < 3; j++) {
                        printf("%d ", *(arr[i] + j));
                }
                printf("\n");
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~$ ./a.out
  0  1  2 
  3  4  5 
  6  7  8 


Pointer to integer

How to declare integer pointer?
Below is the declaration for pointer to integer.
int *ptr;
Here, ptr is a pointer of type int.

What is integer pointer?
Pointer is nothing but referece to a memory location.  If a pointer is of type integer, then it is called integer pointer.  Usually, integer pointer holds the address of interger variable.
int num = 10, *ptr;
ptr = &num;
Here, ptr is an integer pointer and it hold the address of the integer variable num.

Accessing array elements using pointers:
Consider the following example,
int arr[5] = {10, 20, 30, 40, 50};
int *ptr;
ptr = arr;
Here, ptr is a pointer to an array of integer.  And it holds the address of the first element in the integer array arr.  Let us see how to access array elements using pointers
*ptr is 10
*(ptr + 1) is 20
*(ptr + 2) is 30
*(ptr + 3) is 40
*(ptr + 4) is 50


Example c program on integer pointers:


  #include <stdio.h>
  int main() {
        int i, num = 10, *ptr;
        int arr[] = {10, 20, 30, 40, 50};

        /* assigning address of the integer variable */
        ptr = &num;
        printf("num: %d\t*ptr: %d\n", num, *ptr);
        /* adding 10 to the value referred by ptr */
        *ptr = *ptr + 10;
        printf("Current value of num: %d\n", num);

        /* assigning address of the 1st element of the arrary to ptr */
        ptr = arr;

        /* accessing array elements using pointers */
        for (i = 0; i < 5; i++) {
                printf("arr[%d]: %d\n", i, arr[i]);
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~$ ./a.out
  num: 10 *ptr: 10
  Current value of num: 20
  arr[0]: 10
  arr[1]: 20
  arr[2]: 30
  arr[3]: 40
  arr[4]: 50


Array of pointer to structure

Array of pointer to structure is nothing but an array whose elements are pointers to structure

How to declare array of pointer to structure?
Below is an example declaration for array of pointer to structure.
struct student *arr[10];
Here, arr is an array 10 of pointer to structure student.

Dynamic memory allocation:
Below is the procedure to perform dynamic memory allocation for the structure pointers in an array.
struct student {
int age;
char name[32];
};

fun() {
int i = 0;
struct student *arr[10];
for (i = 0; i < 10; i++) {
/* dynamic memory allocation for 5 structure objects */
arr[i] = (struct student *)malloc(sizeof(struct student) * 5);
}
}

Write a c program to pass an array of structure pointers to another function


  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  struct student {
        int age, rollno;
        char name[32];
  };

  /* printing details of students */
  void printData(struct student *arr[2]) {
        int i;
        for (i = 0; i < 2; i++) {
                printf("\nStudent %d:", i + 1);
                printf("Name: %s\n", arr[i]->name);
                printf("Roll: %d\n", arr[i]->rollno);
                printf("Age : %d\n\n", arr[i]->age);
        }
        return;
  }

  int main() {
        int i;
        struct student *arr[2];

        /* dynamic memory allocation for structure pointer in array arr */
        for (i = 0; i < 2; i++) {
                arr[i] = (struct student *)malloc(sizeof(struct student));
        }

        /* assigning values to structure elements */
        strcpy(arr[0]->name, "Ram");
        arr[0]->age  = 10;
        arr[0]->rollno = 1000;
        strcpy(arr[1]->name, "Raj");
        arr[1]->age  = 11;
        arr[1]->rollno = 1001;
        printData(arr);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Student 1:
  Name: Ram
  Roll: 1000
  Age : 10

  Student 2:
  Name: Raj
  Roll: 1001
  Age : 11


Array of function pointers

Array of function pointer is nothing but an array whose elements are function pointers.

How to declare array of function pointer?
Below is an example declaration for array of function pointers.
int (*func[])(int, int);
Here, fun is an array of pointer to function (int, int) returning int

Example c program for array of function pointer


  #include <stdio.h>
  int add(int a, int b) {
        return (a + b);
  }

  int sub(int a, int b) {
        return (a - b);
  }

  int multiply(int a, int b) {
        return (a * b);
  }

  int main() {
        int (*fun[3])(int, int); // array of function pointers
        int a = 20, b = 10, res;

        /* assigning references for function pointers */
        fun[0] = add;
        fun[1] = sub;
        fun[2] = multiply;

        /* calling add() */
        res = (*fun[0])(a, b);
        printf("Addition of %d and %d is %d\n", a, b, res);

        /* calling sub() */
        res = (*fun[1])(a, b);
        printf("Difference b/w %d and %d is %d\n", a, b, res);

        /* calling multiply() */
        res = (*fun[2]) (a, b);
        printf("Product of %d and %d is %d\n", a, b, res);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Addition of 20 and 10 is 30
  Difference b/w 20 and 10 is 10
  Product of 20 and 10 is 200



Write a c program to pass an array of function pointers to another function


  #include <stdio.h>
  int add(int a, int b) {
        return (a + b);
  }

  int sub(int a, int b) {
        return (a - b);
  }

  int multiply(int a, int b) {
        return (a * b);
  }

  void manipulate(int a, int b, int (*fun[3]) (int, int)) {
        int res;
        /* calling add() */
        res = (*fun[0])(a, b);
        printf("Addition of %d and %d is %d\n", a, b, res);

        /* calling sub() */
        res = (*fun[1])(a, b);
        printf("Difference b/w %d and %d is %d\n", a, b, res);

        /* calling multiply() */
        res = (*fun[2]) (a, b);
        printf("Product of %d and %d is %d\n", a, b, res);
        return;
  }

  int main() {
        int (*fun[3])(int, int);
        int a = 20, b = 10;

        /* assinging references for function pointers */
        fun[0] = add;
        fun[1] = sub;
        fun[2] = multiply;
        /* passing array of function pointers as argument */
        manipulate(a, b, fun);
        return 0;
  }


  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Addition of 20 and 10 is 30
  Difference b/w 20 and 10 is 10
  Product of 20 and 10 is 200


Array of character pointers

Consider an array of n elements.  If each element in the array is a pointer to character, then the array is called as array of character pointer.

How to declare array of character pointer?
Below is the declaration for character pointer.
char *arr[10];

How to initialize array of character pointers?
Below is the initialization of array of character pointers.
char *days[7] = { "SUN", "MON", "TUE", "WED",
                           "THU", "FRI", "SAT"};
Here, days is an array of 7 character pointers.  Each character pointer in the array days refers to the string constant at the corresponding index in the array.  For example,
days[0] points to the string constant "SUN"
days[1] points to the string constant "MON"
days[2] points to the string constant "TUE"
days[3] points to the string constant "WED"
days[4] points to the string constant "THU"
days[5] points to the string constant "FRI"
days[6] points to the string constant "SAT"

Dynamic memory allocation for array of character pointers:
Below is the procedure to perform dynamic memory allocation for array of character pointers.
char *days[7];
for (i = 0; i < 7; i++) {
    // allocate memory block of size 32 bytes
days[i] = (char *)malloc(sizeof(char) * 32);
}

How to access data pointed by character pointers in an array?
Below program explains how to access data pointed by character pointer in an array.


  #include <stdio.h>
  int main() {
        int i, ch;
        char *holiday[2] = {"SATURDAY", "SUNDAY"};
        for (i = 0; i < 2; i++) {
                /* access char by char using char pointer */
                while ((ch = *(holiday[0]++)) != '\0') {
                        printf("%c", ch);
                }
                printf("\n");
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  SATURDAY
  SUNDAY



Let us now see how the data are stored in memory in the case of static memory allocation.

  #include <stdio.h>
  int main() {
        int i, j, ch;
        char *holiday[2] = {"SAT", "SUN"}; // char pointer
        for (i = 0; i < 2; i++) {
                j = 0;
                /* loop until null character */
                while(*(holiday[i] + j) != '\0') {
                        /* print the address and value */
                        printf("0x%x => %c\n",
                                (holiday[i] + j), *(holiday[i] + j));
                        j++;
                }
                /* print the address & value of null character */
                printf("0x%x => \\%d\n", (holiday[i] + j), *(holiday[i] + j));
        }
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  0x8048560 => S
  0x8048561 => A
  0x8048562 => T
  0x8048563 => \0
  0x8048564 => S
  0x8048565 => U
  0x8048566 => N
  0x8048567 => \0


From the output, we could infer that the characters in string constants "SUN" and "SAT" are located at consecutive memory locations.

Pointer to character

What is a string?
A string is a sequence of characters terminated with null character '\0'.  Consider the following,
  "Hello World"
Here, "Hello World" is a string of 11 characters.  Size of character is 1 byte.  So, we need 12 byte of memory to store the above string.  One additional byte is to terminate the string with null character.

+----------------------------------+
|H|E|L|L|O| |W|O|R|L|D|\0|  => 11 characters + 1 null character = 12 characters
+----------------------------------+

What is character pointer?
If a pointer points to a memory location of a character, then it is called character pointer. Below is the declaration for character pointer.
char *ptr, ch = 'a';
ptr = &ch;
Here, ptr is a character pointer and it points to the address of the variable ch.

Consider the following,
char *ptr;
ptr = "hello world";
Here, ptr is a pointer to the character array.  And it points to the first character of the string constant "hello world".

Difference between character array and pointer to string constant?
char array[] = "hello world";
Above is the declaration for array of character.  It allocates memory to hold 12 characters(11 character sequence + 1 null character).  And we are allowed to modify value(character) at any index of the array.

char *ptr = "hello world";
Above is the declaration for pointer to a string constant.  Pointer ptr points to the address of the first character of the given string constant.  Any attempt to modify string constant contents would result to segmentation fault.

Pointer to an array of characters:
char array[] = "hello";
char *ptr;
ptr = array;
Here, ptr is a pointer to an array of characters.  Let us see how to access values referred pointers using subscript.
ptr[0] is 'h'
ptr[1] is 'e'
ptr[2] is 'l'
ptr[3] is 'l'
ptr[4] is 'o'

The above statement(ptr = array) doesn't copy the contents of array to ptr.  Instead, it copies the reference of array to pointer ptr.

Let us see how to copy contents of one string to another using pointers.
char arr[] = "hello";
char *ptr = (char *)malloc(10 * sizeof(char));

Now, we are going to copy the contents to array arr to the buffer pointed by pointer ptr
while (*arr != '\0') {
*ptr++ = *arr++;
}
*ptr = '\0';

What is the size of character pointer?
Size of the character pointer is 4 bytes.

Why do we need character pointer?
Dynamic memory allocation can be performed using character pointer.  Consider the following example, user gives input string as command line argument.  We need to copy the input string to another buffer(destination string) and print the contents of the buffer. In this case, we cannot predict the length of the input string. So, static allocation for destination buffer is not possible. Then, the only possibility is dynamic memory allocation. User has to find the length of the string, allocate memory for destination buffer at run time and copy the contents of the input string.


  #include <stdio.h>
  #include <stdlib.h>
  int main(int argc, char **argv) {
        char *dest, *tmp, *src = NULL;
        int len = 0;

        src = argv[1];
        if (!src) {
                printf("Please provide command line input\n");
                return 0;
        }
        // find the length of the input string
        while (src[len] != '\0') {
                len++;
        }

        printf("Length of input string: %d\n", len);

        /*
         * allocate memory for destination buffer -
         * one additional byte is for null character
         */
        dest = (char *)malloc(sizeof(char) * (len + 1));
        tmp = dest;

        /*
         * copy the contents of input string
         * to destination buffer
         */
        while ((*tmp++ = *src++) != '\0');

        // print the ouput
        printf("Output: %s\n", dest);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:$ ./a.out helloworld
  Length of input string: 10
  Output: helloworld



How to pass character pointer to a function?
It's very simple.  User has pass address of the character variable or address of the first element of character array as function argument.  Below example shows how to pass character pointer as argument.


  #include <stdio.h>
  #include <string.h>

  /*
   * copies the contents of the buffer pointed
   * by src to the buffer pointed by dest
   */
  void copystring(char *dest, char *src) {
        while ((*dest++ = *src++) != '\0');
        return;
  }

  int main() {
        char dest[32], src[] = "helloworld";
        /*
         * passing address of first element of
         * character arrays as arguments
         */
        copystring(dest, src);

        // printing the output
        printf("Ouput: %s\n", dest);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/$ ./a.out
  Ouput: helloworld


Sunday, 22 December 2013

Wild Pointers

Key points on wild pointers:
  • If any of the pointer is uninitialized, then that pointer is called wild pointer.
  • Wild pointers won't refer to any valid memory location.
  • Dereferencing wild pointer would cause segmentation fault.

Consider the following, 
int func() {
int *iptr;
char *cptr;
}
Here, iptr and cptr are wild pointers.  Because, they are not initialized to NULL.

int func() {
static int *int_ptr;
char *char_ptr;
}
Here, int_ptr and char_ptr are not wild pointers.  Because, they are static variables.  By default, static variables are initialized to 0.

Below is the example C program on wild pointer.

  #include <stdio.h>
  int main() {
        int *ptr;  // wild pointer
        if (ptr) {
                printf("ptr is not NULL\n");
                *ptr = 10;
                printf("*ptr: %d\n", *ptr);
        }
        return 0;
  }



  Output: (Wild pointer example)
  jp@jp-VirtualBox:~/$ ./a.out
  ptr is not NULL
  Segmentation fault


Far and huge pointers

Far pointer:
Size of the far pointer is 4 bytes and it can point to 1MB of memory.
4 bytes = 32 bits

Far pointer has a 16 bit segment address and a 16 bit offset value.  Below is the declaration for far pointer
char far *ptr;

Consider, a 32 bit address is stored in far pointer.
char far *ptr = 0x82340005

Here, the 16 bit segment address is 0x8234 and offset value is 0x0005.  So, below is the segment offset pair for 0x82340005
segment:offset = 0x8234:0x0005

Let us see how to convert segment offset pair to 20-bit physical address.
Left shift the segment address by 4 bit = 0x8234 << 0x4 = 0x82340

Now, add the left shifted segment address and offset value to get 20 bit physical address.
20 bit physical address = (left shifted segment address)0x82340 + (offset)0x0005 
                                  = 0x82345

The above expression can also be written as follows:
20 bit physical address = (segment address) * (0x10) + offset value
                                    = 0x8234 * 0x10 + 0x0005
                            = 0x82340 + 0x0005 = 0x82345

Consider the following,
char far *ptr1 = 0x82300045;
char far *ptr2 = 0x82200145;

If we convert the above 32 bit addresses to 20 bit physical addressing, both of them points to same location.

But, if you check whether ptr1 equals to ptr2, the condition would fail.  Because, the whole 32 bit address would be used for comparing far pointers using == or !=.

Only offset value will be used for far pointer comparison if the conditional operator is other than ==(equal to) or !=(not equal to). (ie) >, <, >=, <=.  Huge pointer is used in order to overcome the above limitation.


  #include <stdio.h>
  int main() {
       char far *ptr1 = (char far *)0x82340015;
       char far *ptr2 = (char far *)0x82350005;
       printf("Size of far pointer is %d\n", sizeof(ptr1));
       if (ptr1 == ptr2)
              printf("ptr1 and ptr2 are same!!\n");
       else
              printf("ptr1 and ptr2 are not same!!\n");
       if (ptr1 < ptr2)
              printf("ptr1 is less than ptr2!!\n");
       else
              printf("ptr2 is less than ptr1!!\n");
       return 0;
  }



  Output:
  Size of far pointer is 4
  ptr1 and ptr2 are not same!!
  ptr2 is less than ptr1!!



Huge pointer: 
Size of huge pointer is 4 bytes and it can also point to 1 MB of data.
4 bytes = 32 bits

Below is the declaration for huge pointer.
char huge *ptr;

Huge pointer has 16 bit segment address and 16 bit offset value similar to far pointers.

But, huge pointers are normalized pointers.  Let us see how the normalization takes place from the below example.
char huge *ptr1 = 0x82300045;
char huge *ptr2 = 0x82200145;

Convert the above addresses to 20 bit addressing format.
20 bit address of 0x82300045  = 0x8230 * 0x10 + 0x0045 = 0x82345
20 bit address of 0x82200145  = 0x8220 * 0x10 + 0x0145 = 0x82345

Now, split 20 bit address into two parts.  16 bits for segment address and remaining 4 bits for offset.

20 bit address of 0x82300045 is 0x82345
Splitting 20 bit address into two parts - 0x8234(segment address):0x0005(offset value)
Then, the segment offset value pair for 0x82300045 is 0x8234:0x0005

Similarly, 20 bit address of 0x82300145 is 0x82345
Splitting 20 bit address into two parts - 0x8234(segment address):0x0005(offset value)
Then, the segment offset value for 0x82200145 is 0x8234:0x0005

So, the normalized value for 0x82300045 and 0x82200145 is 0x82340005

Now, if you check whether ptr1 is equal to ptr2, the result would be positive.  Because, the normalized value for both 0x82300045 and 0x82200145 is 0x82340005(32 bit address). The same is applicable(32 bit comparison) for other conditional operators too.

In huge pointer, most of the address part is available in segment address.  Whereas, offset has only 4 bit information(ie) offset will have any value from 0 to 0xF.  In our case, offset is 0x0005.  This resolves the limitation of far pointer.


  #include <stdio.h>
  int main() {
      char huge *ptr1 = (char huge *)0x82340015;
      char huge *ptr2 = (char huge *)0x82350005;
      printf("Size of huge pointer is %d\n", sizeof(ptr1));
      if (ptr1 == ptr2)
           printf("ptr1 and ptr2 are same!!\n");
      else
           printf("ptr1 and ptr2 are not same!!\n");
      if (ptr1 <= ptr2)
           printf("ptr1 is less than or equal to ptr2!!\n");
      else
           printf("ptr2 is less than ptr1!!\n");
      return 0;
  }



  Output:
  Size of huge pointer is 4
  ptr1 and ptr2 are not same!!
  ptr1 is less than or equal to ptr2!!



Near Pointer

Compilers like Turbo C supports the following pointers.
1. near pointer
2. far pointer
3. huge pointer

Let us see more details on near pointer.  Size of near pointer is 2 bytes and it can point to only 64 KB of memory.
    2 bytes = 16 bits
    2^16    = 65536 => 64KB
So, near pointer can refer any address from 0 to 65535 (ie) 0x0000 to 0xFFFF

Then, how near pointer can refer memory location beyond 65535th byte.  In DOS environment, only 16 bit data bus(connects microprocessor and memory) and 20 bit address bus would be used.
16 bit data bus      - Capable of transferring 16 bits of data at a time.
20 bit address bus  - 2^20 => Capable of accessing 10,48,576 locations in memory.

1MB = 1024 KB
64KB X 16 = 1024KB

So, 1MB has sixteen 64KB data segments.

+------------+
|    64KB    |  Segment F(15)
+------------+
|    64KB    |     .
+------------+
|    64KB    |     .
+------------+
|    64KB    |  Segment 2
+------------+ 
|    64KB    |  Segment 1
+------------+
|    64KB    |  Segment 0
+------------+

Here, addresses in segment 0 are from 0th byte to 65535th byte.  The memory locations in segment 0 can be accessed using near pointer.  But, it cannot refer any address beyond 65535th byte.  Because, the size of near pointer is only 16 bits(2 bytes).  In order to access memory location beyond 65535th byte, near pointer uses data in 16 bit code/data segment register.  And the near pointer contains the offset part.  65536th byte is present in segment 1.  Hexa decimal format of 65536 is 0x10000.

Then, first four digits hexadecimal digits(ie) 0x1000(0x10000/0x10 = 0x1000)will be stored in code/data segment register.  Whereas the offset 0x0 will be available in near pointer. The conjunction of data in data segment register and near pointer gives us access to memory location beyond 65535th byte.


  #include <stdio.h>
  int main() {
char near *ptr = 0x0000;
printf("Size of near pointer: %d\n", sizeof(ptr));
/* moving one byte ahead */
printf("ptr+1: 0x%04x\n", ptr + 1);
/* moving one byte backward */
printf("ptr-1: 0x%04x\n", ptr - 1);
return 0;
  }



  Output:
  Size of near pointer: 2
  ptr+1: 0x0001
  ptr-1: 0xFFFF



The above program shows that the address referred by near pointer loops circularly from 0x0000 to 0xFFFF.

Saturday, 21 December 2013

Pointer Expressions

Pointers can be used in expressions.  Basically, pointers are preceded by indirection operator(*).  Consider the following example

int a = 10;
int *ptr1, **ptr2;
ptr1 = &a;
ptr2 = &ptr1;

          a
 +---------------+
|       10        |
+---------------+
 Addr of a(&a)
   
&a           -> address of a
*(&a)       -> value of a
ptr1         -> address of a
*(&ptr1)   -> address of a
*ptr1        -> value of a
ptr2         -> address of ptr1
*(&ptr2)   -> address of ptr1
*ptr2       -> value of ptr1/address of a
**ptr2      -> value of a



  #include <stdio.h>
  int main() {
        int a = 10, *ptr1, **ptr2;
        ptr1 = &a;
        ptr2 = &ptr1;
        printf("Address of a => &a       : 0x%x\n", &a);
        printf("Value of a   => *(&a)    : %d\n", *(&a));
        printf("Value of a   => *ptr1    : %d\n", *ptr1);
        printf("Address of a => ptr1     : 0x%x\n", ptr1);
        printf("Address of a => *(&ptr1) : 0x%x\n", *(&ptr1));
        printf("Addr of ptr1 => &ptr1    : 0x%x\n", &ptr1);
        printf("Addr of ptr1 => ptr2     : 0x%x\n", ptr2);
        printf("Addr of ptr1 => *(&ptr2) : 0x%x\n", *(&ptr2));
        printf("Val of ptr1  => *ptr2    : 0x%x\n", *ptr2);
        printf("Value of a   => **ptr2   : %d\n", **ptr2);
        return 0;
  }



  Output:
  jp@jp-VirtualBox:~/cpgms/pointers/posts$ ./a.out
  Address of a => &a          : 0xbfe29b6c
  Value of a   => *(&a)        : 10
  Value of a   => *ptr1        : 10
  Address of a => ptr1        : 0xbfe29b6c
  Address of a => *(&ptr1)  : 0xbfe29b6c
  Addr of ptr1 => &ptr1      : 0xbfe29b68
  Addr of ptr1 => ptr2        : 0xbfe29b68
  Addr of ptr1 => *(&ptr2)  : 0xbfe29b68
  Val of ptr1  => *ptr2        : 0xbfe29b6c
  Value of a   => **ptr2       : 10



Let us try to use pointers in expressions.  Consider the following
int a = 10, b = 20, sum, product;
int ptr1, ptr2;
ptr1 = &a, ptr2 = &b;

sum = *ptr1 + *ptr2;
*ptr1 is 10
*ptr2 is 20
So, the value of sum is 30

The above expression can also be written as follows
sum = (*ptr1) + (*ptr2);

product = *ptr1 * *ptr2;
Here, the value of product is 200

The above expression can also be written as follows
product = (*ptr1)*(*ptr2);
product = *ptr1**ptr2;
product = * ptr1 * * ptr2;

*ptr1++ -> advances the reference of pointer ptr1
++*ptr1 -> increments value referred by ptr1 by 1

++*ptr1 is equivalent to (*ptr1)++
++*ptr1 is equivalent to ++(*ptr1)

The above expression can also be written as follows
*ptr1 = *ptr1 + 1;
*ptr1 + = 1;

*ptr1--  => decrements the reference of pointer ptr1
--*ptr1  => decrements value referred by ptr1 by 1

The above expressions can also be written as follows
*ptr = *ptr - 1;
*ptr -= 1;