Storage Classes in C

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 19

Functions in C Language

In C programming, functions are essential to make the program modular, structured, and
easy to debug. Functions help break large programs into smaller, manageable parts, and can
be reused across different parts of the program.

There are two types of functions in C:

1. User-Defined Functions
2. Built-in Functions (also called Library Functions)

Let's explore both in detail.

1. User-Defined Functions
User-defined functions are those that a programmer creates to perform a specific task. These
functions allow code to be reusable, modular, and easier to manage.

Structure of a User-Defined Function

A typical user-defined function has the following structure:

1. Function Declaration (also called Function Prototype)


2. Function Definition
3. Function Call

Steps Involved:

a) Function Declaration (Prototype)

This tells the compiler about the function name, its return type, and the parameters it accepts.
The declaration typically appears before the main() function.

Syntax:

return_type function_name(parameter_type1 parameter1, parameter_type2


parameter2, ...);

Example:

int add(int a, int b); // Function declaration (prototype)

b) Function Definition

This is where the actual code of the function is written. The definition includes the function
name, parameters, and the body of the function, which performs the task.

Syntax:
return_type function_name(parameter_type1 parameter1, parameter_type2
parameter2, ...) {
// Function body (the code that performs the task)
return value; // if the return type is not void
}

Example:

int add(int a, int b) {


return a + b; // Adds the two numbers and returns the result
}
c) Function Call

The function is invoked (or called) inside another function, usually main(), to perform the task.
When the function is called, control is transferred to the function definition.

Syntax:

function_name(arguments);

Example:

int result = add(5, 10); // Calls the 'add' function with arguments 5 and
10

Example of a User-Defined Function


#include <stdio.h>

// Function declaration
int add(int a, int b);

int main() {
int num1 = 5, num2 = 10;

// Function call
int sum = add(num1, num2);

printf("Sum = %d\n", sum);


return 0;
}

// Function definition
int add(int a, int b) {
return a + b;
}

In the example above:

 The function add() is user-defined to add two integers.


 We declare it first (int add(int a, int b);).
 We define it later (int add(int a, int b) { return a + b; }).
 The function is called inside the main() function (add(num1, num2)).
Why Use User-Defined Functions?

1. Modularity: Breaks complex problems into simpler, reusable blocks.


2. Code Reusability: Once a function is written, it can be called multiple times.
3. Simplified Debugging: Errors are easier to locate in small functions.
4. Maintainability: Functions make programs more organized and easy to update.

2. Built-in (Library) Functions


Built-in functions (or library functions) are functions that are already provided by C
libraries. These functions make programming easier by providing ready-made functionalities,
such as input/output operations, mathematical calculations, string handling, and more.

Some commonly used C libraries:

 stdio.h: For standard input/output functions (e.g., printf(), scanf()).


 math.h: For mathematical functions (e.g., sqrt(), pow()).
 string.h: For string handling functions (e.g., strlen(), strcpy()).
 stdlib.h: For general utility functions (e.g., malloc(), exit()).

Examples of Built-in Functions

a) Input/Output Functions (From stdio.h)

1. printf(): This function is used to print output to the screen.

Syntax:

printf("format string", variables);

Example:

printf("Hello, World!\n");

scanf(): This function is used to take input from the user.

Syntax:

scanf("format string", &variables);

Example:

1. nt num;
2. scanf("%d", &num); // Takes an integer input from the user
3.

b) Mathematical Functions (From math.h)

1. sqrt(): This function calculates the square root of a number.


Syntax:

double sqrt(double x);

Example:

double result = sqrt(16.0); // result = 4.0

 pow(): This function calculates the power of a number. For example, pow(2, 3) gives 8
(2^3).

Syntax:

double pow(double base, double exponent);

Example:

double result = pow(2, 3); // result = 8.0


c) String Functions (From string.h)

1. strlen(): This function returns the length of a string (excluding the null character \
0).

Syntax:

size_t strlen(const char* str);

Example:

int length = strlen("Hello"); // length = 5

strcpy(): This function copies one string into another.

Syntax:

char* strcpy(char* destination, const char* source);

Example:

char dest[20];
strcpy(dest, "Hello World"); // Copies "Hello World" into dest

Why Use Built-in Functions?

1. Time-Saving: These functions are pre-written and optimized, so you don't have to
write them yourself.
2. Reliability: Since they are part of standard libraries, they have been tested
extensively.
3. Ease of Use: Built-in functions make tasks like input/output and mathematical
operations much simpler.
Key Differences Between User-Defined and Built-in Functions

User-Defined Functions Built-in Functions


Created by the programmer to perform Provided by C libraries to handle common
specific tasks. tasks.
Must be declared, defined, and then called. Already defined in libraries; only need to be
called.
Customizable according to the needs of the Not customizable, but they cover many
program. common scenarios.
Examples: add(), calculateArea(), etc. Examples: printf(), scanf(), sqrt(), etc.

Built-in Functions in C Language


stdio.h (Standard Input/Output Library)

This library provides functions for input and output operations, such as reading from or
writing to the console.

a) printf()

 Purpose: Prints formatted output to the console.


 Syntax:

int printf(const char* format, ...);

 Example:

printf("Hello, World!\n");
printf("The value of x is %d\n", x); // %d formats an integer

b) scanf()

 Purpose: Reads formatted input from the user.


 Syntax:

int scanf(const char* format, ...);

 Example:
int x;
scanf("%d", &x); // Reads an integer from the user
c) getchar()

 Purpose: Reads a single character from the standard input.


 Syntax:

int getchar(void);

 Example:
char ch = getchar();

d) putchar()

 Purpose: Writes a single character to the standard output.


 Syntax:

int putchar(int ch);

 Example:
putchar('A');

e) gets() and fgets()

 Purpose: Reads a string (line of text) from standard input.


 Syntax:

char* gets(char* str); // deprecated in modern C


char* fgets(char* str, int n, FILE* stream);

 Example:
char str[50];
fgets(str, 50, stdin); // Reads up to 50 characters

f) puts()

 Purpose: Writes a string to the standard output, followed by a newline.


 Syntax:

int puts(const char* str);

 Example:
 puts("Hello, World!");

2. math.h (Mathematical Functions Library)


This library provides functions for performing mathematical calculations.

a) sqrt()

 Purpose: Returns the square root of a number.


 Syntax:

double sqrt(double x);

 Example:
double result = sqrt(16.0); // result = 4.0

b) pow()

 Purpose: Returns the power of a number (i.e., base^exponent).


 Syntax:

double pow(double base, double exponent);

 Example:
double result = pow(2.0, 3.0); // result = 8.0

c) abs()

 Purpose: Returns the absolute value of an integer.


 Syntax:

int abs(int x);

 Example:
int result = abs(-5); // result = 5

d) ceil()

 Purpose: Returns the smallest integer greater than or equal to a floating-point


number.
 Syntax:

double ceil(double x);

 Example:
double result = ceil(3.2); // result = 4.0

e) floor()

 Purpose: Returns the largest integer less than or equal to a floating-point number.
 Syntax:

double floor(double x);

 Example:
double result = floor(3.8); // result = 3.0

f) sin(), cos(), tan()

 Purpose: Returns the sine, cosine, or tangent of an angle (in radians).


 Syntax:

double sin(double x);


double cos(double x);
double tan(double x);

 Example:
double result = sin(3.14159 / 2); // result = 1.0 (approximation of
sin(90 degrees))

3. string.h (String Handling Library)

This library provides functions for manipulating strings (arrays of characters).

a) strlen()

 Purpose: Returns the length of a string (excluding the null terminator \0).
 Syntax:

size_t strlen(const char* str);

 Example:
int len = strlen("Hello"); // len = 5

b) strcpy()

 Purpose: Copies one string to another.


 Syntax:

char* strcpy(char* destination, const char* source);

 Example:
char dest[20];
strcpy(dest, "Hello");
c) strcat()

 Purpose: Appends (concatenates) one string to another.


 Syntax:

char* strcat(char* destination, const char* source);

 Example:
char str1[20] = "Hello, ";
strcat(str1, "World!"); // str1 becomes "Hello, World!"

d) strcmp()

 Purpose: Compares two strings. Returns 0 if they are equal, a negative value if the
first string is less than the second, and a positive value if the first string is greater.
 Syntax:

int strcmp(const char* str1, const char* str2);

 Example:
int result = strcmp("abc", "abc"); // result = 0 (strings are equal)

e) strncpy() and strncat()

 Purpose: Copies or concatenates a specified number of characters from one string to


another.
 Syntax:

char* strncpy(char* destination, const char* source, size_t n);


char* strncat(char* destination, const char* source, size_t n);

 Example:
 strncpy(dest, "Hello", 3); // Copies "Hel" into dest

4. stdlib.h (Standard Library)

This library provides functions for memory allocation, random number generation, and other
utility functions.

a) malloc(), calloc(), free()

 Purpose: Dynamic memory allocation and deallocation.


o malloc(): Allocates a block of memory.
o calloc(): Allocates and initializes a block of memory.
o free(): Frees allocated memory.
 Syntax:

void* malloc(size_t size);


void* calloc(size_t nitems, size_t size);
void free(void* ptr);

 Example:
int* arr = (int*) malloc(10 * sizeof(int)); // Allocates memory for
10 integers
free(arr); // Frees the allocated memory

b) exit()

 Purpose: Terminates the program immediately.


 Syntax:

void exit(int status);

 Example:
if (error) {
exit(1); // Non-zero value indicates an error
}

c) rand(), srand()

 Purpose: Generates pseudo-random numbers.


o rand(): Returns a random number.
o srand(): Seeds the random number generator.
 Syntax:

int rand(void);
void srand(unsigned int seed);

 Example:
srand(time(0)); // Seed the random number generator
int random_number = rand();

5. ctype.h (Character Handling Functions)

This library provides functions for testing and converting characters.


a) isalpha(), isdigit(), isalnum()

 Purpose: Checks if a character is alphabetic (isalpha()), a digit (isdigit()), or


alphanumeric (isalnum()).
 Syntax:

int isalpha(int ch);


int isdigit(int ch);
int isalnum(int ch);

 Example:
if (isalpha('A')) {
// Character is alphabetic
}

b) toupper(), tolower()

 Purpose: Converts a character to uppercase (toupper()) or lowercase (tolower()).


 Syntax:

int toupper(int ch);


int tolower(int ch);

 Example:
char upper = toupper('a'); // upper = 'A'
Storage Classes in C

In C, storage classes define the scope (visibility), lifetime (duration), and linkage
(accessibility) of variables and functions within a program. They determine where a variable
is stored, how long it stays in memory, and which parts of the program can access it. There
are four primary storage classes in C:

1. auto
2. register
3. static
4. extern

Each storage class modifies the behavior of variables in terms of scope, lifetime, and
linkage. Let’s go over each one in detail.

1. auto Storage Class

 Scope: Local to the block where the variable is defined (i.e., function or loop).
 Lifetime: Exists only during the execution of the block (local to the function).
 Linkage: None (local to the block where it's defined).

The auto keyword is the default storage class for all local variables inside a function. Even if
you don't specify auto, the variables declared inside a function have automatic storage.

Example:
#include <stdio.h>

int main() {
auto int num = 10; // 'auto' is optional here
printf("num = %d\n", num);
return 0;
}

Output:

num = 10

In modern C, you rarely need to use auto explicitly because it’s automatically applied to
local variables.

2. register Storage Class

 Scope: Local to the block where the variable is defined.


 Lifetime: Exists only during the execution of the block.
 Linkage: None (local to the block where it's defined).
 Special behavior: Requests that the variable be stored in a CPU register rather than
in memory, improving speed for frequently accessed variables.

The register keyword is used for variables that require quick access, like loop counters.
However, the actual decision to store the variable in a register is made by the compiler.

Example:
#include <stdio.h>

int main() {
register int i; // Request to store 'i' in a register
for (i = 0; i < 5; i++) {
printf("%d ", i);
}
return 0;
}

Output:

0 1 2 3 4

Note: Accessing the address of a register variable (e.g., with the & operator) is not allowed.

3. static Storage Class

 Scope:
o Inside a function: The variable is local to the function (not visible outside), but
it retains its value between function calls.
o Outside a function (global variable): The variable is visible only in the file
where it is defined.
 Lifetime: Exists throughout the program's execution (even if defined inside a
function).
 Linkage:
o Internal linkage if defined outside a function (visible only in the file).
o No linkage for variables inside a function (only within the function).

The static keyword preserves the value of a variable between function calls.

Example 1: static inside a function


#include <stdio.h>

void count_calls() {
static int count = 0; // Static variable, retains value across calls
count++;
printf("This function is called %d times\n", count);
}

int main() {
count_calls();
count_calls();
count_calls();
return 0;
}

Output:

This function is called 1 times


This function is called 2 times
This function is called 3 times
Example 2: static global variable
#include <stdio.h>

static int global_var = 10; // Visible only in this file

void display() {
printf("Global variable: %d\n", global_var);
}

int main() {
display();
return 0;
}

Output:

Global variable: 10

In this case, global_var is not accessible outside this file, providing encapsulation.

4. extern Storage Class

 Scope: Global (can be used across different files).


 Lifetime: Exists throughout the program's execution.
 Linkage: External linkage (visible across multiple files).
The extern keyword is used to declare a variable that is defined in another file. It is mainly
used when you want to share variables between different files.

Example 1: Declaration of extern variable


File1.c:
#include <stdio.h>

int num = 100; // Definition of the variable

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

File2.c:

#include <stdio.h>

extern int num; // Declaration of the external variable

void display() {
printf("num from another file = %d\n", num);
}

Both files share the same num variable. You can use num in both File1.c and File2.c.

Storage Classes:

Storage Scope Lifetime Linkage Usage


Class
auto Local to the block Local to the None Default for local
block variables, rarely
explicitly used.
register Local to the block Local to the None Requests fast access
block (stored in a CPU
register if possible).
static Local/global Exists for the Internal (if Retains value between
(depends on where lifetime of the global) function calls, restricts
defined) program file-level access.
extern Global (visible Exists for the External Used to declare
across files) lifetime of the variables that are
program defined in other files.

 auto is the default storage class for local variables and doesn’t need to be explicitly
mentioned.
 register is a suggestion to store the variable in a register for faster access, but it’s up
to the compiler.
 static helps preserve the value of a local variable between function calls or restricts
the visibility of a global variable to a single file.
 extern allows sharing variables across multiple files in larger programs.
Functions in C Language: Detailed Explanation with Examples

In C programming, functions are a block of code designed to perform a specific task,


allowing us to organize and reuse code efficiently. In this context, we'll explore:

1. Call by Value
2. Passing Arrays to Functions (Call by Reference)
3. Recursion

1. Call by Value

In call by value, when a function is called, the actual values of the arguments are passed to
the function. Changes made to the parameters inside the function do not affect the original
values.

Example:
#include <stdio.h>

void swap(int a, int b) {


int temp = a;
a = b;
b = temp;
printf("Inside function: a = %d, b = %d\n", a, b);
}

int main() {
int x = 10, y = 20;
printf("Before function call: x = %d, y = %d\n", x, y);
swap(x, y);
printf("After function call: x = %d, y = %d\n", x, y);
return 0;
}
Output:
Before function call: x = 10, y = 20
Inside function: a = 20, b = 10
After function call: x = 10, y = 20
Explanation:

 In the function swap(), values of x and y are copied into a and b. Inside the function,
swapping occurs, but it does not affect x and y in main(). This is because the values are
passed by value, and the function works on copies of the original values.

2. Passing Arrays to Functions (Call by Reference)

When an array is passed to a function, the address of the array is passed, not the actual
elements. This is often referred to as call by reference because the function operates on the
actual data stored in the array.
Example:
#include <stdio.h>

void modifyArray(int arr[], int size) {


for(int i = 0; i < size; i++) {
arr[i] = arr[i] * 2;
}
}

int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);

printf("Before modification:\n");
for(int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");

modifyArray(numbers, size);

printf("After modification:\n");
for(int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");

return 0;
}
Output:
Before modification:
1 2 3 4 5
After modification:
2 4 6 8 10
Explanation:

 The array numbers[] is passed to the function modifyArray(). Inside the function, we
modify the elements of the array by doubling them. Since arrays are passed by
reference, the modifications made in the function reflect in the original array.

3. Recursion

Recursion is a technique where a function calls itself to solve a problem. Recursive functions
are useful for problems that can be broken down into smaller, similar problems (e.g.,
calculating factorial, Fibonacci sequence, etc.).

Key Points About Recursion:

 A base case is essential to stop the recursion, preventing infinite recursion.


 Recursive functions solve the problem by breaking it down into smaller problems.

Example: Calculating Factorial Using Recursion


#include <stdio.h>
int factorial(int n) {
if (n == 0) {
return 1; // Base case: factorial of 0 is 1
} else {
return n * factorial(n - 1); // Recursive call
}
}

int main() {
int number = 5;
int result = factorial(number);
printf("Factorial of %d is %d\n", number, result);
return 0;
}
Output:
Factorial of 5 is 120

Explanation:

The function factorial() calls itself with a decremented value of n until it reaches the base case
(n == 0). This example shows how recursion simplifies a problem by repeatedly breaking it
into smaller parts until it reaches a solvable base case.

Example: Fibonacci Series Using Recursion


#include <stdio.h>

int fibonacci(int n) {
if (n == 0) {
return 0; // Base case 1: Fibonacci of 0 is 0
} else if (n == 1) {
return 1; // Base case 2: Fibonacci of 1 is 1
} else {
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive call
}
}

int main() {
int terms = 10;
printf("Fibonacci Series up to %d terms:\n", terms);
for (int i = 0; i < terms; i++) {
printf("%d ", fibonacci(i));
}
printf("\n");
return 0;
}
Output:
Fibonacci Series up to 10 terms:
0 1 1 2 3 5 8 13 21 34
Explanation:

 The fibonacci() function recursively calculates the Fibonacci numbers by breaking the
problem down into smaller subproblems until it reaches the base cases (Fibonacci of 0
and 1). The function calls itself twice to generate the series.
Key Differences Between Call by Value and Call by Reference (Passing
Arrays)

Feature Call by Value Call by Reference (Arrays)


What is Value of the variables Address of the array
passed?
Modification Does not affect the original value Changes reflect in the original
array
Data type Simple data types (int, char, etc.) Arrays or pointers
Usage Suitable for cases where Used when the original data needs
modification isn't needed modification

You might also like