Function in C

1. Write a function which can accept unknown number of integers (variable argument function) and find their sum.

A C function can take variable number of arguments. Such a function is also called variadic function.

A variable argument function must have at least one mandary argument. Followed by this there can be 0 or more arguments of different types.

printf() and scanf() library functions are very good examples of variadic functions

Variadic functions make use a data type va_list which is an argument pointer. And they have to make use of following macros defined in stadarg.h - va_start(), va_arg(),va_end() and optionally va_copy.

int sum(int n,...)
{
   int m,sum=n;
   va_list lst;
   va_start(lst,n);/*initialises argument pointer*/
   do
   {
      m = va_arg(lst,int);/*extracts one argument and increment the pointer to next*/
      sum+=m;
    }
    while (m!=0);
    va_end(lst);/*must be called at the end*/
    printf("%d",sum);
}
2. What is the difference between
int fn(int);
and
extern int fn(int);

No difference at all.

By default function definitions in C have external linkage. Which means that their identifiers are sent to the linker which resolves them with other occurances in other translation units.

Where as internal linkage objects are not visible in other translation units because their identifiers are not sent to the linker. By using keyword static a function/variable can be made to have a internal linkage.

Variables declared outside of any function also have external linkage by default.

3. What does stdio.h file contain?

stdio.h contains declarations of standard library functions such as printf(), scanf(), fgets() etc. (not their actual definitions) and macro defintions.

In order to use a library function, the program must include the header file which has its declaration.

Note that actual definitions of library functions are available in library files in object code - normally in .so files.

5. What does the function do?
int fun(int n)
{
   if(n==1)
     return 1;
   else
    return n*fun(n-1);
}

It calculates and returns the factorial of a number.

It is a recursive function similar to defintion of factorial.

n! = n*(n-1)!

6. Write a recursive C function to print a number in binary

To print a number n in binary, we can use the following algorithm.
  • print the number n/2 in binary
  • print n%2
That is - we call the function recursively for n/2 and then we print the remainder of n%2. The recursive call is continued as long as n is greater than 1.
void print_binary(int n)
{
   if(n>1)
    {
       print_binary(n/2);
     }
     printf("%d",n%2);
 }
7. Consider the following recursive C function that takes two arguments
unsigned int foo(unsigned int a, unsigned int b)
{
   if (a%b==0)
      return b;
   else    
      return (foo(b,a%b));
}
What is the return value of the function foo when it is called as foo(110, 35)?

Return value : 5

The function is recursive gcd (greatest common divisor - also called hcf) function. It returns the gcd of two numbers.

8. Determine what the following function does.
int func(int n)
{
   if (n==0)
      return 0;
   else
      return (n+func(n-1));
}
Write an iterative function for the same

Function finds the sum of all numbers from 1 to n.
Iterative version of function
int sum(int n)
{
  int sum=0;
  while(n>0)
      sum+=n--;
  return sum;
}
9. Write a recursive function to return gcd of two numbers.

gcd - greatest common divisor of two numbers a and b is a number which is the largest divisor common to both the numbers. It is also called hcf - highest common factor.

According to Euclidean algorithm, gcd of two numbers A and B is

  • gcd(A,B) = B if A%B = 0 i.e. A is divisible by B
  • If not, gcd(A,B) = gcd(B,r) where r = A % B (remainder of A and B)
int gcd(int a,int b)
{
     if(a%b==0)
       return b;
    else
      return gcd(b,a%b);
}
We can write an iterative version of the function
int gcd1(int a,int b)
{
     while(a%b)
    {
       int temp;
       temp = b;
        b = a%b;
        a = temp;
     }
     return b;
}
We can see that in this case, recursive function is much easier to write.

In both the functions, we are assuming that b is the smaller number.
10. Write a recursive function to solve Towers of Hanoi problem.

Towers of Hanoi consists of three rods, and a number of disks of different sizes. To start with, all disks are stacked on first rod, largest one at bottom, smallest at top, in order of diameter.

The aim of the puzzle is to transfer all the disks to another rod with the following conditons

#include<stdio.h>
void towerofhanoi(int num,int frompeg,int topeg,int temppeg)
{
    if(num==1)
       printf("Moving disk %d from peg %d to peg %d\n",num,frompeg,topeg);
   else
   {
      towerofhanoi(num-1,frompeg,temppeg,topeg);
      printf("Moving disk %d from peg %d peg %d\n",num,frompeg,topeg);
      towerofhanoi(num-1,temppeg,topeg,frompeg);
   }
}
int main()
{
    int n;
    printf("Enter teh number of disks:");
    scanf("%d",&n);
    int from,to,temp;
    from = 1;
    to = 3;
    temp = 2;
    towerofhanoi(n,from,to,temp);
    return 0;
}
11. Write a recursive function to print a string in reverse order.

To print a string in reverse, we must print the n-1 characters in reverse, and then print the nth character.

e.g.
 To print Hello in reverse, we have to print ello in reverse and then print H.
                      ... Print llo in reverse, and then print e
                  and so on..
#include<stdio.h>
void print_rev(char *str)
{
   if (*str)
   {
      print_rev(str+1);
      putchar(*str);
   }
}
int main()
{
    char *s = "Hello world";
    print_rev(s);
    return 0;
} 
12. Find error in this function. The function is written to double a given number.
void double(int n)
{
  n*=2;
 }

There are two errors in the function.

  1. And the function produces syntax error, because double is a key word in C( it is a data type) and it can not be used as a function name or any other identifier.
  2. As the function has no return statement, it does not return double of the number. If the function is used in assignment statement, it takes some garbage value.
13. Find the error in this function.
int func(void a1)
{
  return a1-1;
}

There can not be a variable of void type. Hence the parameter defintion is wrong.

Correct function would be:

int func(int  a1)
{
   return a1-1;
}
 
14. How many times the following program will print "Hello world"?
#include<stdio.h>
int main()
{
    printf("Hello world");
    main();
    return 0;
}

Infinte number of times

But remember that this program calls the main function recursively. And will execute again and again, until there is stack overflow and the program crashes.

15. What will be the output of the program?
#include<stdio.h>
void fun(int*, int*);
int main()
{
    int i=5, j=2;
    fun(&i, &j);
    printf("%d, %d", i, j);
    return 0;
}
void fun(int *i, int *j)
{
    *i = *i**i;
    *j = *j**j;
}

Output: 25 4

The function is a call by reference function. i.e. it receives addresses of two variables and modifies them using these addresses - pointers.
16. Point out the error in the following function
f(int a, int b)
{
    int a;
    return a+b;
}

a - which is a parameter is redeclared again as a local variable.

It is not an error to omit the return type of a function. If omitted, return type defaults to int.

17. Find out the error in this program
#include<stdio.h>
int main()
{
    int a=10;
    void f();
    a = f();
    printf("%d\n", a);
    return 0;
}
void f()
{
    printf("Hi");
}

The error is - we are trying to access the return value of void function. Void function does not return anything.

18. Why does scanf() need address of a variable, where as printf needs just name of the variable?

The parameters to a function in C are call by value parameters by default. So a copy of argument is given to function. Even if function modifiets this copy, actual argument is not changed.

If instead the function takes address of a variable as parameter, it can write a value to that address. This is called call by reference parameter.

Since scanf needs to read a variable from standard input device and modify that variable, it needs call by reference method. So it needs address of variable (using &operator).

In fact any function, which should return more than one value will have to use call by reference parameters and address of operator.

19. What are the different data types a C function can return? Which is default return type of a function?

The function can return any data type except for an array or a function.

The return type can be int,float, double, char, struct, union, pointer, or even pointer to function.

If the function returns nothing, the return type should be void.

The default return type of function in C is int. That is, if you write a function without return type, it is treated as int function.

add(int a, int b); 
is same as
int add(int a, int b);

20. How is a function with variable number of arguments defined? Which header file is needed to be included?

A variable argument function or variadic function is written with mandatory fixed argument followed by an ellipsis (...). Ellipsis statnds for variable number of arguments of any type.

Variable argument function needs at least one fixed arguement.

The header file to be included here is "stdarg.h"

Macros va_start,va_arg and va_end defined in the header file stdarg.h, are used for accessing the variable arguments.

e.g.

void print_numbers(float b,int a,...)
{ 
       va_list list1; 
       int m; 
       double n; 
       va_start(list1,a);  /* start the list after a */ 
       m = va_arg(list1,int); /*extract one int from variable list*/ 
       n = va_arg(list1,double); /*extract one double from variable list*/ 
       va_end(list1;);
 }  
 
  1. va_start should specify the variable arg list macro and the last fixed argument. This initializes the variable list.
  2. va_arg extracts one argument at a time. It should specify variable arg list and the data type of argument to be extracted.
  3. The type should be either int or double. All other types will be promoted to these two types.
  4. va_end finalizes the list.

21. Find out the error in this piece of code
int add_num(a,b)
int a;
int b;
{
   int c = a+b;
   return c;
}

No error

This is the old K&R style of writing a function. It is now deprecated. Don't use it.

22. Explain this function.
static int square(int num)
{
   return num*num;
}

Function finds square of a number and returns it.

But the function has internal linkage because of the static keyword in function header. It can be called only in current translation unit(current .c file)

By default ordinary non-static functions have external linkage - the functions can be called from anywhere in the program.

23. What is the output of the following program
#include <stdio.h>
#include <stdarg.h>
int fun(int n, ...)
{
    int i, j = 0, val = 0;
    va_list p;
    va_start(p, n);
    for (; j < n; ++j)
    {
        i = va_arg(p, int);
        val += i;
    }
    va_end(p);
    return val;
}
int main()
{
    printf("%d\n", fun(3, 1, 2, 3));
    return 0;
}

Output : 6

The fucntion

fun()
is a variable argument function. It adds n values from the argument list. The value of n is given by the first argument.
24. Write a recursive function to find the sum of digits of a number.

 #include<stdio.h>
int sum_of_digits(int n)
{
    if(n>0)
      return n%10+sum_of_digits(n/10);
    else
      return n;
}
int main()
{
   int n;
   scanf("%d",&n);
   printf("sum of digits of %d is %d\n",n,sum_of_digits(n));
   return 0;
}
25. What is the output of the program
#include<stdio.h>
int foo(int n);
int main()
{
  int i;
  for(i=0;i<5;i++)
  {
     int num = foo(i);
     printf("%d  ",num);
   }
  return 0;
}

int foo(int n)
{
   static int sum=0;
   sum +=n*n;
   return sum;
}

Output : 0 1 5 14 30

sum is a static variable. Which means it is initialized (in this case to 0) only first time it is called and later retains its value. So next time time it is called, the value of sum is 0+1. Next time, it is 1+2*2 and so on.

26. Can we use a function as parameter to another function? e.g.
 int foo(int n,int bar(int));

No.

A function can not be a parameter to another function. But a function pointer can be a parameter to a function.

27. Can a function have more than one return statement? Can it have no return statement at all? Can a void function have a return statement?

The answer is YES for all three questions.

A return statement of a function serves two purposes. It returns a value back to the caller function. It also stops the execution of the function and contiues the caller function.

If a function has no return statement, the execution continues till the last statement of the function. And the return values is some garbage value.

return statement in a void function is used for termination of the function. And a return statement of a void function is an empty return statement. e.g.

 void printNum(int num)
 { 
      if(num<=0)
          return;
      printf("The number is positive\n");
  }    
28. What is the output of the following program?
#include<stdio.h>
int main()
{
   int square(int n);/*declaration*/
   int a = 10;
   a = square(a);
   printf("%d",a);
   return 0;
}
int square(int n)
{
   int temp = n*n;
}

Output : Garabage value

The function does not print 100 - square of 10. Because the function square does not return temp after calculating it. So a = square(a); assigns some garbage value to a.

29. Write output of the following program
        #include <stdio.h>
        int main()
        {
            int i = 97, *p = &i;
            foo(&i);
            printf("%d ", *p);
        }
        void foo(int *p)
        {
            int j = 2;
            p = &j;
            printf("%d ", *p);
        }
2 97

The function foo() takes a pointer as a parameter. So it is a call by reference parameter. But if we assign the pointer p to another address, that change remains local to the function. And *p remains its old value - 97 in main function.

30. What will happen when the following program is exectued?
#include<stdio.h>
int main()
{
   printf("%p",main);
   return 0;
}

The program prints some address - address of main function.

The first statement of the program just prints the address, it does not call the main function again, as we have not used the paranthesis.

31. Write a function to reverse the digits of an integer

int reverse_integer(int n)
{
  int rev_num = 0;
  while(n)
  {
     int digit = n%10;
     n/=10;
     rev_num = rev_num*10 + digit;
   }
   return rev_num;
}

  • When we divide the number by 10, the remainder is the last digit of the number. This is stored in a variable called rev_num
  • Next the number is divided by 10 using integer division. So that we get a number excluding the last digit
  • Again the number is divided by 10 and the remainder is used.
  • The previous remainder is multiplied by 10 (the digits are shifted to the left) and the new remainder is added to it.
  • This process is continued until the number becomes zero. Now the remainder is the rev_num.
32. Write a function to print all armstrong numbers from 1 to 1000.

An armstrong is a number whose sum of cubes of digits is equal to the number itself.

The function is_armstrong() takes a number as a paramter and finds the sum of cubes of digits and determines whether this sum is equal to the number (condition for an armstrong number) and returns 0, if it is not an armstrong number. Else returns 1.

#include<stdio.h>
int is_armstrong(int num)
{
    int temp = num,sum=0;
    while(temp)
    {
       int digit = temp%10;
       temp /=10;
       sum += digit*digit*digit;
    }
    return sum==num;
}
int main()  
{
    int i;
    int n=1000;
    for(i=1;i<n;i++)
       if(is_armstrong(i))
          printf("%d\t",i);
}
33. Write a program to print numbers from 1 to 100 without using any loops.

#include<stdio.h>
void print_numbers_rec(int n);
int main()
{
   print_numbers_rec(100);
}

void print_numbers_rec(int n)
{
   if(n>0)
   {
      print_numbers_rec(n-1);
      printf("%d ",n);
   }

}

When the function print_numbers_rec() is called with 100, it recursively calls same function with 99 and printf(100) will be stored in stack. This in turn calls print_numbers_rec() with 98 and so on. This process is repeated as long as n is greater than 0. Once n becomes 0, all the printf in stack are unwound and are printed.

34. Write a function to swap two nibbles of a byte. e.g. if the 8 bit number is 0x78, the function should return 0x87

int swap_nibbles(unsigned char n)
{
    unsigned char temp = n;
    n = n>>4;/*most significant 4 bits moved to LS nibble*/
    temp = temp<<4;//least significat nibble becomes most significant*/
    n = n|temp;/*temp has first nibble and n has second nibble. When ORed, n becomes the reversed byte*/
    return n;
}
35. Write a function to check if the given number is in binary number system.

The given number will be in the binary number system, if only digits present in the number are 0 and 1

The function extracts each digit of the number - starting from last. Then it checks if this digit is greater than 1. If yes, it returns a false - a 0. If none of the digits are greater than 1, the function returns a 1 - a true.

int is_binary(int n)
{
    while(n)
    {
       int digit = n%10;
       if(digit>1)
           return 0;
       n/=10;
    }
    return 1;
}
36. Given three sides of a triangle, write a function to find if the triangle is right angled.

A right angled triangle will have to obey Pythogoros's theorem for its sides - the sum of squares of its two sides will be equal to the square of third side.

The function here checks whether a2 = b2+c2 or b2 = a2+c2 or c2 = a2+b2

int is_rt(int a,int b,int c)
{ 
  if(a*a == (b*b+c*c))
            return 1;
  if(b*b == (a*a + c*c))
            return 1; 
  if(c*c == (a*a + b*b))
            return 1;
     return 0;
}
37. Calculate the factorial of a number recursively and from that, calculate the value of ex=1+ (X1/1!) + (X2/2!) + (X3/3!) +...

#include<stdio.h> #include<math.h> #define NUM_TERMS 30 long int factorial(int num) { if(num==0) return 1; else return num*factorial(num-1); } float epowerx(float x) { float sum=1.0; int i; for(i=1;i<NUM_TERMS;i++) { float term = pow(x,i)/factorial(i); sum+=term; } } int main() { float x; printf("x="); scanf("%f",&x); printf("e to power %f is %f\n",x,epowerx(x)); return 0; }

38. Calculate the factorial of a number recursively. From that calculate the value of COS(X) = 1 - X2/2! + X4 /4! - X6/ 6! +??.

 #define NUM_TERMS 30
 #define PI 22.0/7
 long int factorial(int num)
 {
    if(num==0)
       return 1;
    else
       return num*factorial(num-1);
 }
 float cosine(float x)
 {
      float sum =1.0;
      int i;
      int sign = -1;
      x = x * PI/180;/*convert to radians*/
      for(i=2;i<NUM_TERMS;i+=2)
       {
          float term = pow(x,i)/factorial(i);
          sum+=sign*term;
          sign *=-1;
        }
      return sum;
 }
39. Write a program to find LCM of two numbers

#include<stdio.h>
int gcd(int a,int b)
{
     if(a%b==0)
      return b;
    else
      return gcd(b,a%b);
}

int main()
{
  int a,b;
  int gc,lcm;
  printf("Enter 2 numbers:");
  scanf("%d %d",&a,&b);
  gc = gcd(a,b);
  lcm = (a*b)/gc;
  printf("LCM of two numbers is %d\n",lcm);
  return 0;
}
40. Write a program to read a number and print the number in words. e.g. if the number is 785, the output should be seven eight five

#include<stdio.h>
void printDigit(int d)
{ 
   switch(d)
   {
      case 1:printf("ONE");
             break;
      case 2:printf("TWO");
             break;
      case 3:printf("THREE");
             break;
      case 4:printf("FOUR");
             break;
      case 5:printf("FIVE");
             break;
      case 6:printf("SIX");
             break;
      case 7:printf("SEVEN");
             break;
      case 8:printf("EIGHT");
             break;
      case 9:printf("NINE");
             break;
      case 0:printf("ZERO");
             break;
   }
   printf(" ");
}
void findDigits(int n)
{
    if(n>0)
    {
      findDigits(n/10);
      printDigit(n%10);
    }
    
}
int main()
{
  int n;
  printf("Enter a number");
  scanf("%d",&n);  
  findDigits(n);
  return 0;
}
41. What is the return type of a function? Can we omit this return type? If yes how?

The type of return value is the return type of a function.

Return type is specified before the function name in function declaration and definition.

e.g.

int factorial(int n);/*  return type is int   */
void print_sum(int n,int m)
/* return type is void. */ { printf("%d",n+m); }

A return type of a function can be any valid type except for arrays and functions.

It is possible to omit the return type in C. If omitted, the default return type is taken, which is int.

product(int a,int b,int c);/*  return type  - int*/
42. What is call by value parameter?

A C function sends parameter by value - a copy of argument is sent to the function.

The actual argument and function parameter are two different variables stored in two different locations. At function call, value of argument is copied to the parameter.

Because of this, if parameter is modified by the function, the argument in caller function is not changed.

This is called "call by value" mechanism.

Instead if we send address of a variable to function and function has a pointer parameter, then the called function can change the argument using the pointer. (this is known as call by reference)

43. How do you send an array to the function? How do you return an array from the function?

An array is sent to the function by specifying its name - but this array parameter gets implicitly converted to base address of the array. And any changes made to array are also available in the caller function.

The size of the array must also be sent to function. (But for strings - which are character arrays, size is not needed because a string ends in a null character).

void read_array(int arr[],int n);
An array can not be returned from a function. But we can return a pointer to first element of array from a function.

Remember that, if this array which is returned using its pointer is not allocated at run time, there will be errors at run time. Because all local variables including arrays are destroyed when function exits.

int *somefn(){
            int *arr = (int *)malloc(10*sizeof(int));
            return arr;
         }
44. What is call by reference parameter? Why do we need such parameters?

Call by reference parameters are pointers which help the function to modify variables indirectly.

Functions are like black boxes. All variables and parameters used in the function have local scope and are not visible outside. Even the parameters sent to function are just copies of actual arguments.

So the only way of sending value back from function is through return values.

But a function can return only one value. If there is a need to return multiple values from function, we must use call by reference parameter.

A typical example is a function to swap two varaibles.

         void swap(int *p1,int *p2)
         {
                 int temp = *p1;
                 *p1 = *p2;
                 *p2 = temp;
        }
        int main(){
               int a = 10,b=3;
              swap(&a,&b);
       }

Here a and b are sent as reference (pointer) parameter. swap() function changes a and b using the pointers.