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); }
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.
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.
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)!
- print the number n/2 in binary
- print n%2
void print_binary(int n) { if(n>1) { print_binary(n/2); } printf("%d",n%2); }
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.
int func(int n) { if (n==0) return 0; else return (n+func(n-1)); }Write an iterative function for the same
Iterative version of function
int sum(int n) { int sum=0; while(n>0) sum+=n--; return sum; }
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.
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
- Only one disk can be moved at a time.
- Only the disk at the top can be moved and placed on the top of another rod.
- No larger disk may be placed on top of a smaller disk.
#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; }
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; }
void double(int n) { n*=2; }
There are two errors in the function.
- 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.
- 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.
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; }
#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.
#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.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.
#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.
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.
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);
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;); }
- va_start should specify the variable arg list macro and the last fixed argument. This initializes the variable list.
- va_arg extracts one argument at a time. It should specify variable arg list and the data type of argument to be extracted.
- The type should be either int or double. All other types will be promoted to these two types.
- va_end finalizes the list.
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.
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.
#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.
#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; }
#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.
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.
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"); }
#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.
#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.
#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.
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.
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); }
#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.
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; }
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; }
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; }
#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; }
#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; }
#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; }
#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; }
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*/
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)
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; }
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.