Pointers in C Programming

Very Very important topic for exam if you know pointers you can solve 40% exam questions very easily so dont miss anything practice too much .
In simple words, a pointer is an address. It is a derived data type that stores the memory address. A pointer can also be used to refer another pointer, function. A pointer can be incremented/ decremented, i.e., to point to the next/ previous memory location.

How does Pointer Work? :

If we declare a variable v of type int, v will actually store a value.

int v = 0

v is equal to zero now.
However, each variable, apart from value, also has its address (or, simply put, where it is located in the memory). The address can be retrieved by putting an ampersand (&) before the variable name. &v

If you print the address of a variable on the screen, it will look like a totally random number (moreover, it can be different from run to run).

Let’s try this in practice.

                            int main()
                            {
                                int v =0 ;
                                printf("%d\n",&v);
                                return 0;
                            }
                        



The output of this program is -480613588.
Now, what is a pointer? Instead of storing a value, a pointer will y store the address of a variable. Int *y = &v;

 

Declaring a pointer :

The pointer in c language can be declared using * (asterisk symbol). It is also known as indirection pointer used to dereference a pointer.
int *a;//pointer to int

char *c;//pointer to char

Let’s see the pointer example as explained for the above figure.

 
  1. #include<stdio.h>  
  2. int main(){  
  3. int number=50;    
  4. int *p;      
  5. p=&number;//stores the address of number variable    
  6. printf(“Address of p variable is %x \n”,p); // p contains the address of the number therefore printing p gives the address of number.     
  7. printf(“Value of p variable is %d \n”,*p); // As we know that * is used to dereference a pointer therefore if we print *p, we will get the value stored at the address contained by p.    
  8. return 0;  
  9. }    
                        



Output :

                            Address of number variable is fff4
                            Address of p variable is fff4
                            Value of p variable is 50
                    

 

Reference operator (&) and Dereference operator (*) :

& is called reference operator. It gives you the address of a variable.

Likewise, there is another operator that gets you the value from the address, it is called a dereference operator *.

Below example clearly demonstrates the use of pointers, reference operator and dereference operator.

Note: The * sign when declaring a pointer is not a dereference operator. It is just a similar notation that creates a pointer.

Example: How Pointer Works?



                                   # include stdio 
                                    int main()
                                    {
                                       int* pc, c;
                                       
                                       c = 22;
                                       printf("Address of c: %u\n", &c);
                                       printf("Value of c: %d\n\n", c);
                                       
                                       pc = &c;
                                       printf("Address of pointer pc: %u\n", pc);
                                       printf("Content of pointer pc: %d\n\n", *pc);
                                       
                                       c = 11;
                                       printf("Address of pointer pc: %u\n", pc);
                                       printf("Content of pointer pc: %d\n\n", *pc);
                                       
                                       *pc = 2;
                                       printf("Address of c: %u\n", &c);
                                       printf("Value of c: %d\n\n", c);
                                       return 0;
                                    }
                    

Output :

                            Address of c: 2686784
                            Value of c: 22
                            
                            Address of pointer pc: 2686784
                            Content of pointer pc: 22
                            
                            Address of pointer pc: 2686784
                            Content of pointer pc: 11
                            
                            Address of c: 2686784
                            Value of c: 2
                    

 

Explanation of the program :


1. int* pc, c;
Here, a pointer pc and a normal variable c, both of type int, is created.
Since pc and c are not initialized at first, pointer pc points to either no address or a random address. And, variable c has an address but contains a random garbage value.

2. c = 22;
This assigns 22 to the variable c, i.e., 22 is stored in the memory location of variable c. Note that, when printing &c (address of c), we use %u rather than %d since address is usually expressed as an unsigned integer (always positive).

3. pc = &c;

his assigns the address of variable c to the pointer pc.
You see the value of pc is same as the address of c and the content of pc is 22 as well.

4. c = 11;

This assigns 11 to variable c.
Since, pointer pc points to the same address as c, value pointed by pointer pc is 11 as well.

5. *pc = 2;;

This change the value at the memory location pointed by pointer pc to 2.
the address of the pointer pc is same as the address of c, value of c is also changed to 2.

Common mistakes when working with pointers :

Suppose, you want pointer pc to point to the address of c. Then,

                            int c, *pc;
                            // Wrong! pc is address whereas, 
                            // c is not an address.
                            pc = c;  
                            // Wrong! *pc is the value pointed by address whereas, 
                            // &c is an address.
                            *pc = &c; 
                            // Correct! pc is an address and, 
                            // &c is also an address.
                            pc = &c; 
                            // Correct! *pc is the value pointed by address and, 
                            // c is also a value (not address).
                            *pc = c;
                    

 

C Pointers and Arrays:

Now, check this simple program. This program prints address of each individual element of an array.

                                    #include 
                                    int main()
                                    {
                                       int x[4];
                                       int i;
                                       for(i = 0; i < 4; ++i)
                                       {
                                          printf("&x[%d] = %u\n", i, &x[i]);
                                       }
                                       printf("Address of array x: %u", x);
                                       return 0;
                                    }
                    

Output :

                            &x[0] = 1450734448
                            &x[1] = 1450734452
                            &x[2] = 1450734456
                            &x[3] = 1450734460
                            Address of array x: 1450734448
                    

There is a difference of 4 bytes between two consecutive elements of array x. It is because the size of int is 4 bytes (on our compiler).

Notice that, printing &x[0] and x gave us the same result.

Relation between Arrays and Pointers :

Connsider an array :

                            int x[4];
                    


From the above example, it’s clear that x and &x[0] both contains the same address. Hence, &x[0] is equivalent to x.
And, x[0] is equivalent to *x.
Similarly,

&x[1] is equivalent to x+1 and x[1] is equivalent to *(x+1).
&x[2] is equivalent to x+2 and x[2] is equivalent to *(x+2).

… Basically, &x[i] is equivalent to x+i and x[i] is equivalent to *(x+i).

Pointers and Arrays :

 

                                    #include 
                                    int main()
                                    {
                                      int i, x[6], sum = 0;
                                      printf("Enter 6 numbers: ");
                                      for(i = 0; i < 6; ++i)
                                      {
                                          scanf("%d", x+i);
                                          sum += *(x+i);
                                      }
                                      printf("Sum = %d", sum);
                                      return 0;
                                    }
                    

 

Output :

 

                            Enter 6 numbers:  2
                            3
                            4
                            4
                            12
                            4
                           Sum = 29 
                    


In most contexts, array names “decays” to pointers. In simple words, array names are converted to pointers. That’s the reason why you can use pointer with the same name as array to manipulate elements of the array. However, you should remember that pointers and arrays are not same.

 

Lets Do Some exercises on Pointers dont copy code from google :

 

1.Write a program in C to store n elements in an array and print the elements using pointe.

                                Input  Data : 
                                Input the number of elements to store in the array :5 
                                Input 5 number of elements in the array : 
                                element - 0 : 5 
                                element - 1 : 7 
                                element - 2 : 2 
                                element - 3 : 9 
                                element - 4 : 8 
                                
                                Output :
                                
                                 The elements you entered are :                                                                               
                                 element - 0 : 5                                                                                              
                                 element - 1 : 7                                                                                              
                                 element - 2 : 2                                                                                              
                                 element - 3 : 9                                                                                              
                                 element - 4 : 8   
                           



2. Write a program in C to print all permutations of a given string using pointers.
                            The permutations of the abcd  string are  :                                                                         
                            abcd  abdc  acbd  acdb  adcb  adbc  
                            bacd  badc  bcad  bcda  bdca  bdac  
                            cbad  cbda  cabd  cadb  cdab  cdba  dbca 
                            dbac  dcba  dcab  dacb  dabc
                     

 

C Dynamic Memory Allocation

An array is a collection of fixed number of values of a single type. That is, you need to declare the size of an array before you can use it.

Sometimes, the size of array you declared may be insufficient. To solve this issue, you can allocate memory manually during run-time. This is known as dynamic memory allocation in C programming.

There are 4 library functions defined makes dynamic memory allocation in C programming. They are :
1. malloc()
2. calloc()
3. realloc()
4. free()

The process of allocating memory during program execution is called dynamic memory allocation. Lets Start to explore above 4 functions 

C malloc() :

The name “malloc” stands for memory allocation.

The malloc() function reserves a block of memory of the specified number of bytes. And, it returns a pointer of type void which can be casted into pointer of any form.

malloc” or “memory allocation” method is used to dynamically allocate a single large block of memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any form.

Syntax of malloc() :

 

                                    ptr = (cast-type*) malloc(byte-size)

                

Example :

                                ptr = (int*) malloc(100 * sizeof(int));
                                
                

Considering the size of int is 4 bytes, this statement allocates 400 bytes of memory. And, the pointer ptr holds the address of the first byte in the allocated memory.

** Note : ** : However, if the space is insufficient, allocation fails and returns a NULL pointer.

Lets Take an Example :

                    int main()
                    {
                    char name[20];
                    char *address;
                    
                    strcpy(name, "Harry Lee");
                    address = (char*)malloc( 50 * sizeof(char) );  /* allocating memory dynamically  */
                    strcpy( address, "Lee Fort, 11-B Sans Street");
                    
                    printf("Name = %s\n", name );
                    printf("Address: %s\n", address );
                    return 0;
                    }

                
                

In the above example, we assigned and printed the name as we used to do till now. For address, we estimated that the number of characters should be around 50. So, the size of address will be 50 * sizeof(char).

char *address → Here we declared a pointer to character for address without specifying how much memory is required.

address = (char*)malloc( 50 * sizeof(char) ) → By writing this, we assigned a memory of ’50 * sizeof(char)’ bytes for address. We used (char*) to typecast the pointer returned by malloc to character.

strcpy( address, “Lee Fort, 11-B Sans Street”) → By writing this, finally we assigned the address.

 

C calloc() :

The name “calloc” stands for contiguous allocation.

The malloc() function allocates a single block of memory. Whereas, calloc() allocates multiple blocks of memory and initializes them to zero.

Syntax of calloc() :

                        ptr = (cast-type*)calloc(n, element-size);
                

Example:

                        ptr = (float*) calloc(25, sizeof(float));
                


This statement allocates contiguous space in memory for 25 elements each with the size of float.

“calloc” or “contiguous allocation” method is used to dynamically allocate the specified number of blocks of memory of the specified type. It initializes each block with a default value ‘0’.

Lets take and example :

                        int main()
                        {
                            int n,i,*p;
                            printf("Enter number of elements: ");
                            scanf("%d",&n);
                            p=(int*)calloc(n, sizeof(int));  //memory allocated using malloc
                            if(p == NULL)
                            {
                                printf("memory cannot be allocated\n");
                            }
                            else
                            {
                              printf("Enter elements of array:\n");
                              for(i=0;i<n;++i)
                              {
                                scanf("%d",&*(p+i));
                              }
                              printf("Elements of array are\n");
                              for(i=0;i<n;i++)
                              {
                                printf("%d\n",*(p+i));
                              }
                            }
                            return 0;
                        }
                

So, this is same as the example of malloc, with a difference in the syntax of calloc. Here we wrote (int*)calloc(n, sizeof(int)), where n is the number of elements in the integer array (5 in this case) and sizeof(int) is the size of each of that element. So the total size of the array is n * sizeof(int).

 

C calloc() :

The function strncmp compares between two strings, returning the number 0 if they are equal, or a different number if they are different. The arguments are the two strings to be compared, and the maximum comparison length. There is also an unsafe version of this function called strcmp, but it is not recommended to use it. For example:


                        char * name = "John";

                        if (strncmp(name, "John", 4) == 0) {
                            printf("Hello, John!\n");
                        } else {
                            printf("You are not John. Go away.\n");
                        }
                        

 

The realloc Function :

Using the realloc() function, you can add more memory size to already allocated memory. It expands the current block while leaving the original content as it is. realloc stands for reallocation of memory.

realloc can also be used to reduce the size of the previously allocated memory.

Syntax :

                           ptr = realloc (ptr,newsize);
                     


The above statement allocates a new memory space with a specified size in the variable newsize. After executing the function, the pointer will be returned to the first byte of the memory block. The new size can be larger or smaller than the previous memory. We cannot be sure that if the newly allocated block will point to the same location as that of the previous memory block. This function will copy all the previous data in the new region.

Lets take an example :

                                    #include <stdio.h>
                                    int main () {
                                    char *ptr;
                                    ptr = (char *) malloc(10);
                                    strcpy(ptr, "Programming");
                                    printf(" %s,  Address = %u\n", ptr, ptr);
                                 
                                    ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
                                    strcat(ptr, " In 'C'");
                                    printf(" %s,  Address = %u\n", ptr, ptr);
                                    free(ptr);
                                    return 0;
                                 } 
                     



Whenever the realloc results in an unsuccessful operation, it returns a null pointer, and the previous data is also freed.

 

calloc vs. malloc: Key Differences :

The calloc function is generally more suitable and efficient than that of the malloc function. While both the functions are used to allocate memory space, calloc can allocate multiple blocks at a single time. You don’t have to request for a memory block every time. The calloc function is used in complex data structures which require larger memory space.

The memory block allocated by a calloc function is always initialized to zero while in malloc it always contains a garbage value.

C free() :

 

Dynamically allocated memory created with either calloc() or malloc() doesn’t get freed on their own. You must explicitly use free() to release the space.
Syntax is very simple :

                        free(ptr)
                     


Above statement frees the space allocated in the memory pointed by ptr.

Lets take and simple Programming example to understand better :

                                 #include  <stdio.h >
                                 #include  <stdlib.h >
                                 int main()
                                 {
                                     int n, i, *ptr, sum = 0;
                                     printf("Enter number of elements: ");
                                     scanf("%d", &n);
                                     ptr = (int*) malloc(n * sizeof(int));
                                     if(ptr == NULL)                     
                                     {
                                         printf("Error! memory not allocated.");
                                         exit(0);
                                     }
                                     printf("Enter elements: ");
                                     for(i = 0; i < n; ++i)
                                     {
                                         scanf("%d", ptr + i);
                                         sum += *(ptr + i);
                                     }
                                     printf("Sum = %d", sum);
                                     free(ptr);
                                     return 0;
                                 }
                     

 

Some important differences :

malloccalloc

The name malloc stands for memory allocation.

The name calloc stands for contiguous allocation.

void *malloc(size_t n) returns a pointer to n bytes of uninitialized storage, or NULL if the request cannot be satisfied. If the space assigned by malloc() is overrun, the results are undefined.

void *calloc(size_t n, size_t size) returns a pointer to enough free space for an array of n objects of the specified size, or NULL if the request cannot be satisfied. The storage is initialized to zero.

malloc() takes one argument that is, number of bytes.

calloc() take two arguments those are: number of blocks and size of each block.

syntax of malloc():

void *malloc(size_t n);

Allocates n bytes of memory. If the allocation succeeds, a void pointer to the allocated memory is returned. Otherwise NULL is returned.

 

syntax of calloc():

void *calloc(size_t n, size_t size);

Allocates a contiguous block of memory large enough to hold n elements of size bytes each. The allocated region is initialized to zero.

 

malloc is faster than calloc.

 

calloc takes little longer than malloc because of the extra step of initializing the allocated memory by zero. However, in practice the difference in speed is very tiny and not recognizable.

Try to understand all above concepts exam will ask some tricky questions on it .

Like some complex snippets but if you are clear in your basic concepts you can solve very easily