Introduction
Functions are a set of statements that are combined to perform a specific task.
Ø A user-defined function is a type of function in C language that is defined by the user himself to perform some specific task.
Ø It provides code reusability and modularity to our program.
Ø User-defined functions are different from built-in functions as their working is specified by the user and no header file is required for their usage.
Ø Syntax
return_type function_name (type1 arg1, type2 arg2 .... typeN argN) {
// actual statements to be executed
// return value if any
}
Benefits of User-Defined Functions
Ø Reusability: One of the main benefits of user-defined functions is that they can be reused in different parts of a program. Instead of writing the same code multiple times, you can define a function and call it whenever you need to perform a specific task.
Ø Modularity: User-defined functions promote modularity in a program by breaking it down into smaller, manageable parts. It makes it easier to understand the code and debug any issues that may arise.
Ø Simplified code: User-defined functions can simplify the code by abstracting away complex logic into a single function. It makes the code easier to read and understand.
Ø Better testing: By breaking down a program into smaller functions, it becomes easier to test each function individually. It makes it easier to identify and isolate issues within the code, making it easier to fix any bugs and improve the overall quality of the program.
Components
Ø There are three components of the function definition:
Ø Function Parameters
Ø Function Body
Ø Return Value
Ø Function Parameters
Ø Function parameters (also known as arguments) are the values that are passed to the called function by the caller.
Ø We can pass none or any number of function parameters to the function.
Ø We have to define the function name and its type in the function definition and we can only pass the same number and type of parameters in the function call.
Ø Example:
Ø int name(int a, int b);
Ø Here, a and b are function parameters.
Ø Function Body
Ø The function body is the set of statements that are enclosed within { } braces.
Ø They are the statements that are executed when the function is called.
Ø Example:
int name(int a, int b) {
int sum = a + b;
return sum;
}
Here, the statements between { and } is function body.
Ø Return Value
Ø The return value is the value returned by the function to its caller.
Ø A function can only return a single value and it is optional.
Ø If no value is to be returned, the return type is defined as void.
Ø The return keyword is used to return the value from a function.
Ø Syntax
Ø return (expression);
Ø Example
int name(int a, int b) {
return a + b;
}
Library Function vs. Users Defined Function
How to use User-Defined
Functions in C?
Ø To use a user-defined function, we first have to understand the different parts of its syntax.
Ø The user-defined function in C can be divided into three parts:
Ø Function Prototype
Ø Function Definition
Ø Function Call
Function Prototype
Ø A function prototype is also known as a function declaration which specifies the function’s name, function parameters, and return type.
Ø The function prototype does not contain the body of the function.
Ø It is basically used to inform the compiler about the existence of the user-defined function which can be used in the later part of the program.
Ø Syntax
Ø return_type function_name (type1 arg1, type2 arg2, ... typeN argN);
Ø We can also skip the name of the arguments in the function prototype. So,
Ø return_type function_name (type1 , type2 , ... typeN);
Function Definition
Ø Once the function has been called, the function definition contains the actual statements that will be executed.
Ø All the statements of the function definition are enclosed within { } braces.
Ø Syntax
return_type function_name (type1 arg1, type2 arg2 .... typeN argN) {
// actual statements to be executed
// return value if any
}
Ø Note: If the function call is present after the function definition, we can skip the function prototype part and directly define the function.
Function Call
Ø In order to transfer control to a user-defined function, we need to call it.
Ø Functions are called using their names followed by round brackets.
Ø Their arguments are passed inside the brackets.
Ø Syntax
Ø function_name(arg1, arg2, ... argN);
Program to illustrate the function call
#include<stdio.h>
int sum(int,int); //Funtion Prototype
//function Defination
int sum(int a,int b) {
return (a+b);
}
void main() {
int x=5,y=6;
int total;
total = sum(x,y); //function call
printf("The sum of x and y is: %d",total);
}
Function Parameters
Ø When we call a function in main() or anywhere else in the program, and the function we created needs parameters, we would pass parameters to it while calling the function.
Ø In the previous example, we passed variables x and y to obtain the sum of x and y.
Ø According to the example above, the formal parameters are a and b, and the actual parameters are x and y.
Ø Essentially, the variables being passed in the function call are actual parameters, and the variables being initialized and used in the function are formal parameters.
Different Forms of Function
Ø The user-defined functions are further divided into four types on the basis of arguments and return value processing:
Ø Functions with arguments and return values.
Ø Functions with arguments and without return values.
Ø Functions without arguments and with return values.
Ø Functions without arguments and without return values.
Functions with arguments and return values
#include <stdio.h>
int sub(int,int);
void main() {
int x=10,y=7;
int res = sub(x,y);
printf("x-y = %d",res);
}
int sub(int a,int b) {
int c = a - b;
return c;
}
Functions
with arguments and without return values
#include
<stdio.h>
void
sub(int,int);
void
main() {
int x=10,y=7;
sub(x,y);
}
void
sub(int a,int b) {
int c = a-b;
printf("x-y = %d",c);
}
Functions without arguments and with return
values
#include
<stdio.h>
int sub();
void
main() {
int res = sub();
printf("a-b = %d",res);
}
int sub()
{
int a = 10, b = 7;
int c = a - b;
return c;
}
Functions without arguments and without return
values
#include
<stdio.h>
void
sub();
void
main() {
sub();
}
void
sub() {
int a = 10, b = 7;
int c;
c = a - b;
printf("The difference of a and b is
%d.",c);
}
Recursion
The
process in which a function calls itself directly or indirectly is called recursion.
The
corresponding function is called a recursive function.
Using a
recursive algorithm, certain problems can be solved quite easily. Examples of
such problems are
Fibonacci
Series, factorial, reversing an integer, checking prime number, etc.
we should
provide a certain case in order to terminate this recursion process.
Principle of Recursion
Ø A recursive function has two different parts.
Ø The base case and the recursive case.
Ø The base case is used to terminate the task of recurring. If base case is not defined, then the function will recur infinite number of times
Ø In computer program, when we call one function, the value of the program counter is stored into the internal stack before jumping into the function area.
Ø After completing the task, it pops out the address and assign it into the program counter, then resume the task.
Ø During recursive call, it will store the address multiple times, and jumps into the next function call statement.
Ø If one base case is not defined, it will recur again and again, and store address into stack. If the stack has no space anymore, it will raise an error as “Internal Stack Overflow”.
Example
Ø One example of recursive call is finding the factorial of a number.
Ø We can see that the factorial of a number n = n! is same as the n * (n-1)!, again it is same as n * (n - 1) * (n - 2)!.
Ø So if the factorial is a function, then it will be called again and again, but the argument is decreased by 1.
Ø When the argument is 1 or 0, it will return 1. This could be the base case of the recursion.
int fact(int n)
{
if (n < = 1) // base case
return 1;
else
return n*fact(n-1);
}
WAP to find the Fibonacci series using recursion
#include<stdio.h>
int fibonacci(int);
int main(){
int n, i;
printf("Enter the number of element you want in series :");
scanf("%d",&n);
printf("fibonacci series is : \n");
for(i=0;i<n;i++) {
printf("%d \n",fibonacci(i));
}
return 0;
}
int
fibonacci(int n) {
if(n==0)
return 0;
else if(n==1)
return 1;
else
return
(fibonacci(n-1)+fibonacci(n-2));
}
WAP to find the reverse of an integer.
int
revNumFunction(int num){
if(num){
rem=num%10;
sum=sum*10+rem;
revNumFunction(num/10);
}
else
return sum;
}
Passing Array to Function
In C programming, you can pass an entire array to functions.
Passing array elements to a function is similar to passing variables to a function.
we need to pass only the name of the array in the function which is intended to accept an array.
The array defined as the formal parameter will automatically refer to the array specified by the array name defined as an actual parameter.
Syntax:
Function_name(array_name); //passing array
#include <stdio.h>
float calculateSum(float num[]);
void display(float []);
int main() {
float result, num[] = {23.4, 55, 22.6, 3, 40.5, 18};
printf("The elements in array are: ");
display(num);
result = calculateSum(num);
printf("\nSum = %.2f", result);
return 0;
}
float
calculateSum(float num[]) {
int i;
float sum = 0.0;
for (i=0;i<6;++i) {
sum += num[i];
}
return sum;
}
void
display(float num[]) {
int i;
for(i=0;i<6;i++){
printf("%.2f ",num[i]);
}
}
Passing String to Function
We know
that strings are saved in arrays so, to pass an one dimensional array to a
function we will have the following declaration.
Syntax:
returnType
functionName(char str[]);
Example:
void
displayString(char str[]);
In the
above example we have a function by the name displayString and it takes an
argument of type char and the argument is an one dimensional array as we are
using the [] square brackets.
Passing one dimensional string to a function
To pass a
one dimensional string to a function as an argument we just write the name of
the string array variable.
In the
following example we have a string array variable message and it is passed to
the displayString function. Example:
#include
<stdio.h>
void
displayString(char []);
int main()
{
char message[] = "Hello World";
displayString(message);
return 0;
}
void
displayString(char str[]) {
printf("String: %s\n", str);
}
Another
way we can print the string is by using a loop like for or while and print
characters till we hit the NULL character.
In the
following example we have redefined the displayString function logic.
#include
<stdio.h>
void
displayString(char []);
int
main(void) {
char message[] = "Hello World";
displayString(message);
return 0;
}
void displayString(char
str[]) {
int i = 0;
printf("String: ");
while (str[i] != '\0') {
printf("%c", str[i]);
i++;
}
}
Function declaration to accept two dimensional
string
In order
to accept two dimensional string array the function declaration will look like
the following.
Syntax:
returnType
functionName(char [][C], type rows);
Example:
void
displayCities(char str[][50], int rows);
In the
above example we have a function by the name displayCities and it takes a two
dimensional string array of type char.
The str is
a two dimensional array as because we are using two [][] sqaure brackets.
It is
important to specify the second dimension of the array and in this example the
second dimension i.e., total number of columns is 50.
The second
parameter rows tell us about the total number of rows in the given two
dimensional string array str.
Passing two dimensional string to a function
#include
<stdio.h>
void
displayCities(char [][50], int rows);
int
main(void) {
char cities[][50] =
{"Bangalore","Chennai","Kolkata","Mumbai","New
Delhi" };
int rows = 5;
displayCities(cities, rows);
return 0;
}
void
displayCities(char str[][50], int rows)
{
int r, i;
printf("Cities:\n");
for (r
= 0; r < rows; r++) {
i = 0;
while(str[r][i] != '\0') {
printf("%c", str[r][i]);
i++;
}
printf("\n");
}
}
Accessing a function (Function calling)
A function
call is an important part of the C programming language.
It is
called inside a program whenever it is required to call a function.
It is only
called by its name in the main() function of a program.
We can
pass the parameters to a function calling in the main() function.
There are
two different methods of calling a function in the C programming language:
Call by value
In this
method, we will be calling a function by value.
we send a
copy of the actual variable to the function while calling it.
Because of
this, any change in the value of this variable inside the body of the function
is not reflected outside.
When
single or multiple values of an actual argument are copied into the formal
parameter of a function, the method is called the Call by Value.
Hence, it
does not alter the function's actual parameter using the formal parameter.
WAP to simulate the function call by value.
#include
<stdio.h>
Void
main() {
int x = 10, y = 20;
printf (" x = %d, y = %d from main
before calling the function", x, y);
newValue(x, y);
printf( "\n x = %d, y = %d from main
after calling the function", x, y);
}
void newValue( int x, int y) {
x = x +
3;
y = y +
5;
printf
(" \nx = %d, y = %d from function", x, y);
}
Call by reference
In this
method, the address of the actual argument is copied into the function call's
formal parameter; the method is known as Call by Reference.
If we make
some changes in the formal parameters, it shows the effect in the value of the
actual parameter.
we send a
reference of the actual variable to the function while calling it which is why
any change in the value of this variable inside the body of the function is
also reflected outside.
WAP to simulate the function call by reference.
#include
<stdio.h>
void main()
{
int x =
10, y = 20;
printf
(" x = %d, y = %d from main before calling the function", x, y);
newValue
(&x, &y);
printf(
"\n x = %d, y = %d from main after calling the function", x, y);
}
void
newValue( int *a, int *b) {
*a = *a +
5;
*b = *b +
5;
printf
(" \nx = %d, y = %d from function", *a, *b);
}
Macros
Ø A macro is a piece of code in a program that is replaced by the value of the macro.
Ø Macro is defined by #define directive.
Ø Whenever a macro name is encountered by the compiler, it replaces the name with the definition of the macro.
Ø Macro definitions need not be terminated by a semi-colon(;).
Ø Types Of Macros
Ø Object-like Macros
Ø Chain Macros
Ø Multi-line Macros
Ø Function-like Macro
Object-like Macros
Ø An object-like macro is a simple identifier that will be replaced by a code fragment.
Ø It is called object-like because it looks like an object in code that uses it.
Ø It is popularly used to replace a symbolic name with numerical/variable represented as constant.
#include <stdio.h>
#define PI 3.14
int main()
{
printf("The value of the
PI is %.2f", PI);
return 0;
}
Chain Macros
Ø Macros inside macros are termed as chain macros.
Ø In chain macros first of all parent macro is expanded then the child macro is expanded.
#include <stdio.h>
// Macro definition
#define INSTAGRAM FOLLOWERS
#define FOLLOWERS 138
int main()
{
printf(“Our college have %dK
followers on Instagram", INSTAGRAM);
return 0;
}
Multi-line Macros
Ø An object-like macro could have a multi-line.
Ø So to create a multi-line macro you have to use backslash-newline.
#include <stdio.h>
// Multi-line Macro definition
#define ELE 1, \
2, \
3
void main() {
int arr[] = { ELE };
printf("Elements of Array
are:\n");
for (int i = 0; i < 3; i++)
{
printf("%d ", arr[i]);
}
}
Function-like Macro
Ø
These
macros are the same as a function call. It replaces the entire code instead of
a function name.
Ø
Pair of
parentheses immediately after the macro name is necessary.
Ø
If we
put a space between the macro name and the parentheses in the macro definition,
then the macro will not work.
Ø
A
function-like macro is only lengthened if and only if its name appears with a
pair of parentheses after it.
Ø
If we
don’t do this, the function pointer will get the address of the real function
and lead to a syntax error.
#include <stdio.h>
// Function-like Macro definition
#define min(a, b) (((a) < (b)) ? (a) : (b))
int main() {
int a = 18;
int b = 76;
printf("Minimum value
between %d and %d is %d\n",a, b, min(a, b));
return 0;
}
WAP to find the area of a circle
by defining AREA(r) Macros.
#include
<stdio.h>
#define PI
3.1416
#define AREA(r)
(PI*(r)*(r))
int main()
{
float r = 7; // radius of circle
printf("Area of Circle with radius %f:
%.3f", r, AREA(r));
return 0;
}
Advantages of Macros
Ø
Increased
productivity:
Ø
Macros can
save time and reduce errors by automating repetitive tasks.
Ø
Customization:
Ø
Macros can
be customized to fit specific needs, allowing for greater flexibility in how
tasks are completed.
Ø
Consistency:
Ø
Macros can
help ensure consistency in tasks by following a set of predetermined
instructions.
Ø
Efficiency:
Ø
Macros can
perform tasks more quickly than humans, improving overall efficiency.
Ø
Ease of
use:
Ø
Macros are
easy to create and use, requiring little to no programming knowledge
Disadvantages of Macros
Ø
Security
risks:
Ø
Macros can
be a security risk if they are not properly secured or if they are used to
execute malicious code.
Ø
Limited
functionality:
Ø
Macros may
not be able to perform more complex tasks, limiting their usefulness.
Ø
Compatibility
issues:
Ø
Macros may
not be compatible with all software applications, limiting their usefulness.
Ø
Maintenance:
Ø
Macros may
require maintenance and updates, which can be time-consuming and costly.
Ø
Dependence:
Ø
Over-reliance
on macros can result in decreased problem-solving skills and critical thinking.
Storage Class
Ø
We use the
storage class in the C language for determining the visibility, lifetime,
initial value, and memory location of any given variable.
Ø
The
storage classes define the visibility (scope) and the lifetime of any function/
variable within a C program, which help us to trace the existence of a
particular variable during the runtime of a program.
Ø
These
classes precede the type that they are going to modify.
Ø
Types
of Storage Classes in C
Ø
Automatic
Storage Class
Ø
External
Storage Class
Ø
Static
Storage Class
Ø
Register
Storage Class
Summary of Storage Classes in C
Automatic Storage
Class
Ø It is also known as the auto storage class, and it acts as the default storage class for all the variables that are local in nature.
Features of automatic variables:
Ø The allocation of memory for these variables occurs automatically during the runtime.
Ø The scope of an automatic variable is limited to that block in which we are defining them.
Ø The visibility of these variables is also limited to that block in which we are defining them.
Ø The initialization of these variables is, by default, a garbage value.
Ø The memory that is assigned to an automatic variable gets free when it exits from a block.
Ø We use the keyword auto to define the automatic variables.
Ø Any local variable that exists in the C language is, by default, automatic in nature.
Automatic Storage
Class (Example)
#include <stdio.h>
int main() {
int p; //auto
char q;
float r;
printf(“%d %c %f”,p,q,r); // to print the initial default value of the automatic variables p, q, and r.
return 0;
}
#include <stdio.h>
int main() {
int p = 10,i;
printf("%d ",++p);
{
int p = 20;
for (i=0;i<3;i++) {
printf("%d ",p); // 20 will be printed here 3 times because it is the given local value of p
}
}
printf("%d ",p); // 11 will be printed here since the scope of p = 20 has finally ended.
}
External Storage
Class
Ø It is also known as the extern storage class, and we use it for giving a reference of any global variable which is visible to all the files present in a program.
Ø When using the extern storage class, we cannot initialize the variable.
Ø However, note that it points to the name of the variable at any storage location that we have already defined (previously).
Ø Whenever we have multiple numbers of files while we are trying to define any global variable or a function (that will be used in various other files too), then we will use the extern in another file for providing the reference of the defined function or variable.
Ø In simpler words, we use the extern for declaring a function or a global variable in another file.
Features External
Storage Class
Ø We use the external storage class for conveying to the compiler that the variable that has been defined as the extern has been declared using an external linkage that exists elsewhere in any program.
Ø One can only perform the initialization of an external variable globally. In other words, one cannot perform the initialization of an external variable within any given method or block.
Ø The variables that are declared as extern have no allocation of memory. It only has a declaration, and it intends to specify that the given variable has been declared elsewhere in the available program.
Ø An external integral type’s default initial value is going to be 0, or else it is null.
Ø We can initialize an external variable multiple times, but we can only initialize it a single time.
Ø When we declare a variable as external, the compiler will start searching for that variable for initialization somewhere in the available program. It might be static or extern. In case it isn’t, the compiler will ultimately generate an error (a compile-time error).
External Storage
Class (Example)
#include <stdio.h>
int a;
int main() {
extern int a; // variable a is defined globally, the memory will not be allocated to a
printf(“%d”,a);
}
#include <stdio.h>
int main() {
extern int x; // The compiler will start searching here if a variable x has been defined and initialized in the program somewhere or not.
printf(“%d”,x);
}
int x = 20;
extern int x;
int x = 10;
#include <stdio.h>
int main() {
printf(“%d”,x);
}
int x = 20; // the compiler will generate an error at this line in the output
Static Storage Class
Ø This type of storage class gives an instruction to a compiler to keep the given local variable around during the program’s lifetime- instead of creating it and then destroying it every time it comes into a scope and goes out of it.
Ø Thus, when we make a local variable static, it allows the variable to maintain the values that are available between various function calls.
Ø We may also apply a static modifier to a global variable.
Ø When we do so, it will cause the scope of the variable to be restricted to that file in which its declaration happened.
Ø In a C programming language, when we use the static on a global variable, it will cause all the objects present in a class to share a single copy of that given member.
Features of Static
Storage Class
Ø Those variables that we define as static specifiers are capable of holding their assigned value that exists between various function calls.
Ø The static local variables are only visible to the block or the function in which we have defined them.
Ø We can declare the very same static variable multiple times, but we can only assign it a single time.
Ø The initial value of a static integral variable, by default, is 0. Else, it is null.
Ø We use the static keyword in the case of a static variable.
Ø The visibility of any static global variable stays limited to that file in which we have declared it.
Static Storage Class
(Example)
#include<stdio.h>
static float f;
static int i;
static char c;
static char s[100];
void main () {
printf(“%d %d %f %s”,c,i,f); // the initial default value of c, i, and f will be printed.
}
#include<stdio.h>
void sum() {
static int x = 20;
static int y = 34;
printf(“%d %d \n”,x,y);
x++;
y++;
}
void
main() {
int a;
for(a = 0; a< 3; a++) {
sum(); // Given static variables
will hold their values between the various function calls.
}
}
Register Storage
Class
Ø We use the register storage class for defining the local variables that must be stored in any register, and not in a RAM.
Ø It means that the maximum size of this variable is equal to that of the register size (it is usually one word).
Ø Also, we cannot apply the ‘&’ unary operator to it because it has no memory location.
Ø For example: register int miles;
Ø We must only use the register in the case of those variables which require quick access, such as the counters.
Ø We must also note that defining a register doesn’t mean that this variable would be stored in any register.
Ø It rather means that this variable MIGHT or might not be stored in a register. It totally depends on the hardware and also the restrictions of implementation.
Features of Register Storage
Class
Ø Those variables that we define as the register have their memory allocation into the CPU registers. It depends totally upon the size of the memory that remains in the CPU.
Ø Its access time is comparatively much faster than that of the automatic variables.
Ø One cannot dereference a register variable. In other words, one cannot make use of the ‘&’ operator in the case of a register variable.
Ø The default initial value of any given register local value will always be 0.
Ø We use the register keyword for the variable that must be stored in a CPU register. However, whether a variable must be stored in a register or not is always going to be the choice of the compiler.
Ø One can easily store the pointers in a register. It means that any register is capable of storing the given variable’s address.
Ø We cannot store a variable into a register since we can’t really utilize more than one storage specifier for the very same variable.
Register Storage
Class (Example)
#include <stdio.h>
int main()
{
register int x; // A variable x has memory allocation in the CPU register. Here, the initial value of x, by default, is 0.
printf(“%d”,x);
}
No comments:
Post a Comment