Pointers in C

1. What is the difference between int(*ptr)[10],int *ptr,int (*ptr)(int)?

  • int (*ptr)[10] is a pointer to an array of 10 integers. e.g.
     int arr[10]={1,2,3};
     int (*ptr)[10];
     ptr = &arr;//ptr points to array arr
     
  • int *ptr is a pointer to an integer
    e.g.
     int a = 12;
     int *b;
     b = &a;
     
  • int (*ptr)(int) is a pointer to a function which takes one integer parameter and returns an integer
    e.g.
     int cube(int n);
     int (*ptr2)(int);
     ptr2 = cube;
    
2. What is the difference between malloc and calloc? What is realloc?

Both malloc and calloc allocate memory dynamically and return a pointer to begining of block allocated.

But the difference is malloc allocates memory block, but does not initialize the values inside the block.

Calloc allocates memory and initializes each bit with 0 after allocating.

Calloc takes two parameters - number of elements to be allocated and size of one element and malloc takes only one parameter - total size to be allocated.

Both of these functions return a pointer to allocates block.

int *ptr1,*ptr2;
ptr1 = (int*)malloc(20*sizeof(int));
ptr2 = (int*)calloc(20,sizeof(int));/*the block has all 0 values*/

realloc is used to change the size of memory block allocated. If there is insufficient place, it moves the block to a different address.

It takes two parameters - pointer and its new size.

realloc(ptr1,40*sizeof(int));

Here the memory block is expanded to hold 40 integers and ptr1 points to begining of block.

Note that

  1. if ptr1 in the above example is NULL, realloc works exactly like malloc.
  2. If second parameter (new size) is 0, realloc works like free

You should type cast the pointer to the required type with all these functions.

3. Can we have a void function?A void variable? A void pointer?

Yes, no and yes.

  • void function : If a function does not return anything, its return type should be void. Such a function still can contain empty return statement.

    e.g.
    void print_larger(int a,int b)
    {
      if(a>b)   
       {     
         printf("%d",a); 
         return;
       }
       printf("%d",b);
      }
      
  • void variable : We can not have a void variable.
  • void pointer: We can have a void pointer which is a generic pointer. Void pointer can be type-cast and used to point at any type of variable. The dynamic memory allocation functions malloc, calloc and realloc do return a void pointer.
But remember that, it is an error to dereference the void pointer directly (without type casting). e.g.
       void *ptr;  
       int a =12;      
       ptr = (int*)&a;//ok      
       a = *ptr+10;/*error. typecasting should be used*/

4. Consider the following three C functions :
[P1] 
int * g (void)
{
  int x = 10;  return (&x);
}

[P2] 
int * g (void)
{
  int * px;  *px = 10;
  return px;
}

[P3] 
int *g (void)
{
  int *px;
  px = (int *) malloc (sizeof(int));
  *px = 10;  return px;
}
Which of the above three functions are likely to cause problems with pointers?

Both P1 and P2

P1 may not behave correctly because the function returns address of a local automatic variable which will not exist once the function terminates.

P2 causes run time error because px is derefernced without initializing it.

5. What does the following program print?
#include<stdio.h>
void f(int *p, int *q)
{
    p = q;
    *p = 2;
}
 int i=0, j=1;
int main()
{
    f(&i, &j);
    printf("%d %d \n", i, j);
    return 0;
}

Output : 0 2

6. What does the following fragment of C program print?
char c[] = "A tricky question";
char *p =c;
printf("%s", p + p[2] -p[3]) ;
 

Output : tricky question

p is character pointer and it points to the string A tricky question. When you add p[2]-p[3] to p, it becomes p+'t'-'r' = p+2. Which points to the string tricky question

7. What would be the output of the following program
void func(int ( *p)[3]);
int main(){
     int x[2][3] = { {4,5,6},{7,8,9}};
    func(x);
    func(x+1);
}

void func(int (*p)[3])
{
    printf("%d %d %d\n",(*p)[0],(*p)[1],(*p)[2]);
}

Output:
4 5 6
7 8 9

The parameter p to the function func() is a pointer to one dimensional array. When the function is called with x, the argument will be x[0] - the 0th of the array. When next it is called with x+1, the argument sent will be 1st row of the matrix. The function dereferences the pointer and prints the 0th , 1st and 2nd element of this sub-array.

8. What is the difference between const char * and char * const?

 const char *p1;
 char * const p2;
 

p1 is a pointer to a character constant. Which means character pointed by p1 is constant. But the pointer is not constant.

*p1 = 'z' ;
would be wrong.
p1 = "aaa" ;
- is fine.

p2 is a constant pointer to a character. Here pointer is constant. But character is not. Which means we can not assign another value to p2. But we can change the character pointed by p2

 p2 = "mnop" ;
is wrong
*p2 = 'a' ;
is fine

We can even have
const char  * const p3 = "Hello world";

p3 is a constant pointer to constant character. Here neither address nor character can be modified.

Another point of interest is all pointers assigned to string literals are pointers to char constants. Which means the strings they are pointing to can not be modified.

 char *str = "Hello world";
 *str = 'h';
 
Second line in the above code causes the program to crash in some systems. Modifying a string literal produces an undefined behavior.
9. Write a function to insertion sort of an array using pointers.

int insertionsort(int *arr,int n)
{
    int i,j,temp;
    for(i=1;i<n;i++)
    {
        temp=*(arr+i);
        j=i-1;
       while(temp<*(arr+j)&&j>=0)
       {
           *(arr+(j+1))=*(arr+j);
           j--;
       }
      *(arr+(j+1))=temp;
    }
  return 0;
}
10. What is the output of this C code?
#include <stdio.h>
#include <string.h>
int main()
{
         char *str = "hello, world\n";
         char *strc = "good morning\n";
         strcpy(strc, str);
         printf("%s\n", strc);
         return 0;
 }

The program crashes with segmentation fault

The program tries to modify a value pointed by strc which is a pointer pointing to a string literal. Such a pointer is a pointer to a constant character - the value pointed by such a pointer can't be modified. Hence the program crashes.

11. What is the output of this C code?
#include <stdio.h>
 int main()
{
         char *str = "hello, world\n";
         str[5] = '.';
         printf("%s\n", str);
        return 0;
}

Crashes with segmentation fault

str is a pointer to a string literal. Such a string literal will be normally stored in a read only section. That is why we can't change the charactes of this string.

12. What is the output of the following program
#include <stdio.h>
int main()
{
            char *str = "hello world";
            char strary[] = "hello world";
            printf("%d %d\n", sizeof(str), sizeof(strary));
            return 0;
}

4 and 12 in 32 bit machines.

str is a pointer. So its size is the same as size of a pointer - which is size of an integer.

strary is a string array with 11 characters. But its size is 12 - because of the trailing null character - '\0'. (Strings always have null character as last character.)

13. What is a dangling pointer and what is NULL pointer?

A dangling pointer is the one which is used after the memory allocated to it is released using free. Because the pointer is not pointing to any valid address, the result is unpredictable.

int *ptr = malloc(100*sizeof(int));
-------
------
free(ptr);
*ptr = 12;/*using ptr after free. dangling pointer*/

NULL pointer is a predefined pointer pointing to location 0. It is defined as (void*)0 in stdio.h and stdlib.h. Functions which return a pointer, often return NULL to indicate failure.

Null pointer should never be derefernced. If it is derefernced, the program will crash.

14. What is memory leak?

If memory blocks allocated dynamically in a program (using malloc or calloc) are not released using free(), your program will run out of heap memory in due time. This is called memory leak.

15. What is void pointer?

A void pointer is a generic pointer. It is defined as

void *ptr;
This void pointer can be used to store address of any type of variable.

But if a void pointer is deferenced without type casting, compiler gives error.
void *ptr;
 int a; float b;
 ptr = (int *)&a;
 ptr = (float*)&b;
 *ptr=5;/*syntax error*/
*(int *)ptr = 5;//correct

malloc, calloc and realloc return a void pointer.

16. What arithmetic operations are allowed with pointers?

Only operations allowed with pointers are :

  • You can add or subtract an integer to a pointer.
  • You can subtract 2 pointers.
Note that when you add/subtract integer to a pointer, it gets scaled by size of the pointed variable.
e.g. if you add 1 to integer pointer in 32 bit machine, the pointer gets incremented by 4 bytes so that it can point to next integer.
int a;float b;double c; 
char d;
int *ptr1 = &a;/* say a is at location 1000 and it is 4 byte machine*/
float *ptr2 = &b;/*say b is at location 3000*/
double *ptr3 = &c;/*say c is at location 4000*/
char *ptr4 = &d;
ptr1++;/*now ptr1 is 1004*/
ptr1 +=5;/*now ptr1 is 1024*/
ptr2 = ptr2 - 3;/*now ptr2 is 2988 */
ptr3++;/* now ptr3 is 4008*/
ptr4+=5;/*ptr4 is 4005*/
ptr1*=2;/* error*/
ptr2 = ptr1+ptr2;/*error*/
17. Declare x as pointer to a function which takes a character pointer as parameter and returns an integer pointer.

int *(*x)(char*)
18. When is an array in an expression is not implicitly converted to a pointer?

It is not converted to a pointer when using & (address of ) operator and when using sizeof operator.

 int arr[3]={1,2,3};
 arr[1]=24;/* is converted to *(arr+1) = 24*/
 add_num(arr,12);/* parameters sent are &arr[0] and 12*/
 
 l = sizeof(arr);/* is 3*sizeof(int) . Not sizeof(&arr[0]) */
 int *ptr = &arr+1;/* if arr is stored at 1000, ptr will be 1012.  no implicit conversion*/

19. What is the output of the following program?
#include<stdio.h>
int main()
{
  int a,b,c,d;
  char *p = ( char *)0;
  int *q = ( int *)0;
  float *r = ( float *)0;
  double *s = 0;
  a = (int)(p+1);
  b = (int)(q+1);
  c = (int)(r+1);
  d = (int)(s+1);
  printf("%d %d %d %d",a,b,c,d);
  return 0;
}

1 4 4 8
for 32 bit computer

When you perform any arithmetic operations on pointers, these are scaled by the size of the pointee. If you add 1 to an integer pointers, you infact will add 4 to the number.

If you add 1 to double pointer, it gets added by 8 and so on.

20. What will be output of following program?
#include<stdio.h>
int main()
{
  int i = 3;
  int *j;
  int **k;
  j = &i;
  k = &j;
  printf("%u %u %u",i,*j,**k);
  return 0;
}

3 3 3

Here j is a pointer to integer and it points to i. Which means *j is i.

k is a pointer to pointer to integer and it points to j. And **k is again i. So the program prints the value of i three times.

21. What error is stopping the program from printing 30? How do you correct it?
# include <stdio.h>
void fun(int x)
{
    x = 30;
}

int main()
{
  int y = 20;
  fun(y);
  printf("%d", y);
  return 0;
}

x is a value parameter to the function fun(). So x is another copy of y. Which means changing x will not change y. Hence the program will print 20 instead of 30.

To fix the problem, you need to send a reference paramter as shown below

  void fun(int *x)
  {
     *x = 30;
  }
  int main()
  {
     int y = 20;
    fun(&y);/*send address of y to function*/
    printf("%d",y);
    return 0;
  }

Other method is by returning a value from function fun
  int fun(int x)
  {
     x = 30; 
     return x;
  }
  int main()
  {
     int y = 20;
     y = fun(y);
  }
22. Assume that float takes 4 bytes, predict the output of following program.
#include <stdio.h>
int main()
{
    float arr[5] = {12.5, 10.0, 13.5, 90.5, 0.5};
    float *ptr1 = &arr[0];
    float *ptr2 = ptr1 + 3;

    printf("%f ", *ptr2);
    printf("%d", ptr2 – ptr1);

    return 0;
}

90.5 3

ptr1 points to 0th element of the array. When we add 3 to ptr, the result will be pointer to 3rd element of the array. Hence the program prints arr[3].

23.
#include<stdio.h>
int main()
{
   int a;
   char *x;
   x = (char *) &a;
   a = 512;
   x[0] = 1;
   x[1] = 2;
   printf("%d\n",a);
   return 0;
}
What is the output of above program?

513

x is a character pointer. So x[0] will p

24. Is line number 2 correct. If yes, why?
int arr[3] = {1,22,333};
2[arr]= 44;

Though the statement looks ridiculous, it is correct.

C compiler converts any array expression into a pointer expression.

So arr[3] = 3[arr] =*(arr+3)

25. What do the following declarations mean?
int* a1[8];
int (*a2)[8];
int (*a3)(int[]);
  • a1 is an array of 8 integer pointers.
  • a2 is a pointer to an array of 8 integers.
  • a3 is a pointer to a function which takes integer array as a parameter and returns an integer
26.
#include <stdio.h>
 int main()
{
     char *a = {"p", "r", "o", "g", "r", "a", "m"};
     printf("%s", a);
 }

What is the output of this program?

p

If you expect the output to be program, you are wrong. Elements of array are enclosed in double quotes. So they are character strings, not characters. That's why a will be pointing to first string p.

To make a point to the string program , you can define it as

char *a = {'p','r','o','g','r','a','m','\0'};
27. If the size of integer is 4 bytes, What will be the output of the program?
#include<stdio.h>
int main()
{
    int arr[] = {12, 13, 14, 15, 16};
    printf("%d, %d, %d\n", sizeof(arr), sizeof(*arr), sizeof(arr[0]));
    return 0;
}

20 4 4

Size of arr = number of elements X size of each element in bytes = 5X4 = 20.

*arr and arr[0] both are 0th element of the array and their size is 4 bytes each.

28. Write function to calculate sum or product of 3 numbers using a function pointer argument. Write also the necessary functions and code to call this function for both these cases.

#include<stdio.h>
int sum(int a,int b,int c)
{
    return a+b+c;
}
int product(int a,int b,int c)
{
    return a*b*c;
}
int operate(int(*fptr)(int,int,int),int a,int b,int c)
{
     return fptr(a,b,c);
}
int main()
{
    int x,y,z;
    x = 2;y=4;z=6;
    printf("product is %d\n",operate(product,x,y,z));
    printf("sum is  %d\n",operate(sum,x,y,z));
 }
29. Write a function to swap the values of two variables using pointers and without using a third variable

void swap(int *ptr1,int *ptr2)
{
    *ptr1 = *ptr1+*ptr2;
    *ptr2 = *ptr1-*ptr2;
    *ptr1 = *ptr1-*ptr2;
}
int main()
{
   int i=10,j=20;
   swap(&i,&j);
   return 0;
}
30. Using typedefine, define INTPTR as integer pointer and use this to define two integer pointers.

#include<stdio.h>
typedef int * INTPTR;
int main()
{
       INTPTR p1,p2;
       int a,b;
       a = 10;
       b = a;
       p1 = &a;
       p2 = &b;
       printf("Sum of a and b is %d\n", *p1+*p2 );
        return 0;
}
31. How do you define a pointer? How do you assign address of a variable to it?

A pointer is defined with its name, type of pointee and the symbol *.

Syntax

  data-type * var-name;

e.g.
   
       int *ptr;   
       float *p2;

Here we are defining ptr as integer pointer and p2 as float pointer.

To assign an address to it, we use & (address of) operator.

int a = 10;
       int *ptr;
       ptr = &a;

Now ptr points to a.

32. What is indirection operator?

An indirection operator is used to give value at the address specified by ptr. This operator is the same used for multiplication also - *

    
int *ptr;
int a;
ptr = &a;
*ptr = 12;

Now *ptr gives us "a".

The statement *ptr=12 assigns 12 to a indirectly.

Indirection operator and address of operator (* and &) are complimentory to each other.

33. What is a function pointer? How do you define a function pointer?

A function pointer is a pointer which stores address of a function.

If void foo();
is a function, then foo (without paranthesis) or &foo is address of this function and is also a function pointer.

To define a function pointer syntax used is

ret-type (*name)(parameter-list);

e.g.

   void (*ptr)() 
is a function pointer which points to a function which takes no parameter and returns nothing.

Similarly to define a function pointer which takes an array and int as parameter and returns int, we should write

   int (*ptr)(int arr[],int n)

Function pointers are used to implement call back functions

A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

34. With an example, explain how a function pointer is used.

A function pointer is a pointer which holds address of a function.

e.g.
int (*ptr)(int,int)

This defines ptr as a function pointer to a function which returns an integer and takes two integer parameter.

Remember that type of a pointer to a function is based on both the return type and parameter types of the function. Also, declaration of a pointer to a function must have the pointer name in parentheses.

Next this pointer must be assigned to address of a function with similar signature.

Let us say sum function.

ptr = sum;
or
ptr = &sum  ;

sum should be of the type
int sum(int a,int b);

To invoke sum() using function pointer, we must dereference it and provide arguments if needed.e.g.

int ans = (*ptr)(10,10);

This calls sum function with parameters 10 and 10.

35. Define the following
  1. Pointer to an integer
  2. Pointer to pointer to integer
  3. Pointer to an array of 3 integers
  4. Array of 3 integer pointers
  5. Pointer to function which return an int and takes an int parameter.

  1. int *ptr;
  2. int **ptr;
  3. int (*ptr)[3];
  4. int *ptr[3];
  5. int (*ptr)(int);