0% found this document useful (0 votes)
6 views130 pages

C Programming History and Fundamentals

The document provides an overview of the C programming language, detailing its history, evolution, and significance in modern computing. It covers key milestones such as the creation of C in 1972, the standardization processes, and the introduction of various C standards over the years. Additionally, it discusses character sets, type conversions, and library functions essential for programming in C.

Uploaded by

varshitham799
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views130 pages

C Programming History and Fundamentals

The document provides an overview of the C programming language, detailing its history, evolution, and significance in modern computing. It covers key milestones such as the creation of C in 1972, the standardization processes, and the introduction of various C standards over the years. Additionally, it discusses character sets, type conversions, and library functions essential for programming in C.

Uploaded by

varshitham799
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

PRAGATHI DEGREE COLLEGE

(AFFLIATED TO BENGALURU NORTH UNIVERSITY)


(College Code: 7713)
Opp. Whitefield Railway Station, Kadugodi, Bengaluru-560067

DEPARTMENT OF COMPUTER SCIENCE (BCA)


SARANYA S [Link]
ASSISTANT PROFESSOR

STATE EDUCATION POLICY(SEP)-2024-25


STUDY MATERIAL
C PROGRAMMING

1
UNIT I

OVERVIEW OF C LANGUAGE

HISTORY OF C

The history of C programming is both fascinating and foundational to the development of


modern computing. Here's a detailed account of how C evolved:

1. Pre-C Programming

 1960s: Early Programming Languages


o Before C, early programming languages like FORTRAN and ALGOL were
primarily used for scientific calculations and high-level programming.
However, these languages were either too complex or lacked features suitable
for system programming.
o BCPL (Basic Combined Programming Language), developed in the 1960s by
Martin Richards, was a simplified programming language designed for
writing system software. It inspired Ken Thompson and Dennis Ritchie to
create languages that could be more efficient and portable.
 1969: The Birth of B
o In 1969, Ken Thompson developed the B programming language at Bell
Labs while working on the UNIX operating system. B was based on BCPL
and was used for early system development. However, B lacked certain
features needed for more advanced programming tasks.

2. The Creation of C (1972)

 1972: Dennis Ritchie and C


o Dennis Ritchie, working at Bell Labs, developed the C programming
language in 1972 as an enhancement of the B language. C added important
features, such as data types (e.g., integers, characters) and more powerful
control structures.
o The main goal behind C was to provide a language that could efficiently write
the UNIX operating system. Prior to C, UNIX was written in assembly
language, which made it difficult to port to different hardware platforms. C
allowed UNIX to be rewritten in a more portable and flexible way.

2
3. C's Early Impact

 1973: Rewriting UNIX in C


o By 1973, much of the UNIX operating system had been rewritten in C. This
was a pivotal moment because it showcased the language’s power and
flexibility. C allowed the UNIX operating system to be easily ported to
different types of hardware, which was a significant improvement over
previous systems.
o This led to C's adoption by many other researchers and institutions, and it
began to gain momentum in the development of other operating systems and
system software.
 1978: "The C Programming Language" by Brian Kernighan and Dennis Ritchie
o In 1978, Brian Kernighan and Dennis Ritchie published the book "The C
Programming Language", often referred to as K&R C. This book became
the standard reference for the C language and played a major role in
promoting the language to a wider audience.
o K&R C is the version of C that was most widely used in the 1970s and 1980s
before official standardization began.

4. Standardization of C

 1983: ANSI C
o As C became widely adopted, it was important to standardize the language to
ensure consistency across different compilers and platforms. In 1983, the
American National Standards Institute (ANSI) began work on
standardizing C.
o The ANSI C standard was finalized in 1989, known as C89. This version
added clearer rules for function declarations, the inclusion of function
prototypes, and stricter syntax rules.

3
 1990: ISO C
o Following ANSI C, the International Organization for Standardization
(ISO) also adopted the ANSI standard in 1990, making the C language more
universally accepted across the globe.

5. Modern C (1990s and 2000s)

 1999: C99 Standard


o The C99 standard was introduced in 1999, which introduced several new
features to the language:
 Inline functions
 Support for boolean types
 Variable-length arrays
 Improved standard library functions
o C99 brought significant improvements to C, but its adoption was slow as older
compilers did not fully support the new features.
 2011: C11 Standard
o The C11 standard, finalized in 2011, focused on improving C's concurrency
features. It introduced:
 Multithreading support (via <threads.h>)
 Atomic operations for better thread synchronization
 Improved Unicode support
o The C11 standard aimed to modernize C and make it more suitable for current
hardware and applications.

6. C Today

 C17/C18 (2017):
o The C17 (sometimes referred to as C18) standard, introduced in 2017, was a
bug-fix release that made minor improvements but didn't introduce any major
new features. It was a stabilization of C11.
 C's Ongoing Influence
o Despite the rise of other programming languages, C remains one of the most
important languages in modern computing. It continues to be used in:
 Embedded systems (e.g., microcontrollers)

4
 Operating systems (e.g., UNIX, Linux, and BSD)
 Compilers and system software
 Low-level hardware interfaces
o Languages like C++, C#, and Objective-C are all influenced by C, and the
basic structure and syntax of C continue to influence newer languages such as
Java, Python, and JavaScript.

7. C's Legacy

 C is considered a "low-level" language, giving developers direct access to memory


and system hardware while maintaining portability. It provides a balance between
high-level abstractions and low-level control.
 C's influence is still pervasive in system programming, networking, compilers, and
game development. Many programming languages trace their roots back to C, and it
remains one of the most important languages for developers to learn, especially in
fields that demand performance optimization and control over hardware.

CHARACTER SET

In C programming, a character set refers to the collection of characters that can be used in
the source code. These characters are used for defining variables, writing instructions, and
creating programs. The C language defines a standard character set, which includes letters,
digits, punctuation, and special characters. These are classified into several categories.

1. Basic Character Set in C

The C programming language uses the ASCII (American Standard Code for Information
Interchange) character set as its basic character set. The standard ASCII character set contains
128 characters (values 0 to 127). However, modern systems often use extended ASCII or
other encoding schemes (like Unicode) to support additional characters.

Here are the categories of characters in C:

5
2. Types of Characters in C

1. Letters (Alphabetic Characters)

 Lowercase letters: a, b, c, ..., z


 Uppercase letters: A, B, C, ..., Z
 These characters are used for naming variables, functions, and other identifiers in C.

2. Digits (Numerical Characters)

 Digits: 0, 1, 2, 3, ..., 9
 These are used for forming numeric constants and performing arithmetic operations.

3. Special Characters

Special characters have specific meanings and functions in C. Some examples include:

 Whitespace characters: These include space (' '), horizontal tab (\t), newline (\n),
carriage return (\r), and form feed (\f). These characters are used for formatting and
separating code but are not directly used for computation.
 Punctuation characters:
o Comma (,), period (.), semicolon (;), colon (:), question mark (?), exclamation
mark (!), etc.
 Operators and symbols:
o Arithmetic operators: +, -, *, /, %
o Relational operators: ==, !=, <, >, <=, >=
o Logical operators: &&, ||, !
o Bitwise operators: &, |, ^, ~, <<, >>
o Assignment operator: =
o Others: =, ?, :, [], {}

4. Escape Sequences

Escape sequences are special combinations of characters that represent specific actions or
characters, particularly those that can't be directly typed in the code. Examples include:

 \n : Newline (line break)

6
 \t : Horizontal tab
 \\ : Backslash
 \' : Single quote
 \" : Double quote
 \0 : Null character (marks the end of a string)
 \r : Carriage return

5. Comments

C allows two types of comments:

 Single-line comments: Denoted by //, used to comment a single line.

// This is a single-line comment

 Multi-line comments: Enclosed between /* and */, used for commenting multiple
lines.

/* This is a multi-line
comment that spans multiple lines */

3. Character Data Type

In C, the char data type is used to store individual characters. A char variable can hold one
character at a time and takes up 1 byte of memory (typically).

Example:

char ch = 'A'; // char data type stores a single character

 The char type can also store ASCII values, which represent characters. For example,
'A' has the ASCII value of 65.

4. String Literals

A string in C is an array of characters terminated by a null character ('\0'). A string literal is a


sequence of characters enclosed in double quotes.

7
Example:

char str[] = "Hello, World!";

In this example, str is an array of characters with the following values: {'H', 'e', 'l', 'l', 'o', ',', ' ',
'W', 'o', 'r', 'l', 'd', '!', '\0'}.

5. Extended Character Set

While the standard ASCII character set includes 128 characters (0-127), many modern
systems use extended ASCII or Unicode encoding to represent characters beyond the
standard ASCII range (values 128–255 for extended ASCII). Unicode can represent a much
wider variety of characters, including characters from non-Latin alphabets, special symbols,
and emojis.

6. Summary of C Character Set Categories

Category Characters

Letters a-z, A-Z

Digits 0-9

Whitespace Space (' '), Tab (\t), Newline (\n), Carriage Return (\r)

Special Characters +, -, *, /, =, !, ;, ,, :, etc.

Escape Sequences \n, \t, \\, \r, \", \', \0, etc.

Comments //, /*...*/

String Literals "Hello World!" (terminated by '\0')

Extended Supports characters beyond ASCII (e.g., special


ASCII/Unicode symbols, different languages)

C TOKENS

8
9
IDENTIFIERS, KEYWORDS,
DATATYPES,VARIABLES,CONSTANTS,SYMBOLIC CONSTANTS

10
11
12
13
14
15
16
17
Symbolic Constants in C are constants that are defined using a name (identifier) rather than
a direct value. These constants are useful because they make the code more readable and
maintainable. In C, symbolic constants are typically defined using the #define pre processor
directive.

18
Syntax:

#define CONSTANT_NAME value

CONSTANT_NAME: The name of the symbolic constant.

 value: The value assigned to the constant.

Example:

#include <stdio.h>

#define PI 3.14 // Defining symbolic constant for PI


#define MAX_LIMIT 100 // Defining symbolic constant for maximum limit

int main() {
float area;
float radius = 5.0;

// Using the symbolic constant PI


area = PI * radius * radius;

printf("Area of the circle: %.2f\n", area);


printf("Max Limit: %d\n", MAX_LIMIT);

return 0;
}

19
20
21
22
23
24
In C programming, type conversions and library functions are essential tools for
manipulating data types and performing various operations. Below is an overview of both
concepts:

1. Type Conversions in C

Type conversion refers to converting one data type to another. There are two types of type
conversion in C:

a) Implicit Type Conversion (Automatic Type Conversion)

 Implicit conversion is done automatically by the compiler when there is a need to


convert one data type to another. It usually happens when a value is assigned to a
variable of a larger or compatible type.

Example:

int i = 10;
float f = i; // Implicit conversion from int to float
printf("%f", f); // Output: 10.000000

o In this case, the integer i is automatically converted into a float when assigned
to f.

b) Explicit Type Conversion (Casting)

 Explicit conversion (also called type casting) is done manually by the programmer.
You need to specify the target type in parentheses.

Example:

float f = 10.5;
int i = (int)f; // Explicit conversion (casting) from float to int
printf("%d", i); // Output: 10

o In this case, the float value 10.5 is cast to an integer, resulting in 10.

25
2. Library Functions in C

C provides a wide range of library functions that you can use for various tasks such as
mathematical operations, input/output handling, string manipulation, memory management,
etc.

a) Mathematical Functions (math.h)

The math.h library provides various mathematical functions.

 Example Functions:

#include <math.h>

double result;
result = sqrt(16); // Square root
result = pow(2, 3); // Power (2^3)
result = fabs(-4.5); // Absolute value
result = sin(3.14); // Sine function
result = cos(3.14); // Cosine function
b) Input/Output Functions (stdio.h)

The stdio.h library provides functions for input and output operations.

 Example Functions:

#include <stdio.h>

int main() {
printf("Hello, World!"); // Output a message
int num;
scanf("%d", &num); // Take user input for an integer
printf("You entered: %d", num);
return 0;
}

26
c) String Handling Functions (string.h)

The string.h library provides functions for string manipulation.

 Example Functions:

#include <string.h>
char str1[] = "Hello";
char str2[20];

strcpy(str2, str1); // Copy str1 into str2


strcat(str1, " World!"); // Concatenate " World!" to str1
int len = strlen(str1); // Get the length of str1
d) Memory Management Functions (stdlib.h)

The stdlib.h library provides functions for memory allocation and deallocation.

Example Functions:

#include <stdlib.h>
int *ptr = (int*)malloc(sizeof(int)); // Dynamically allocate memory
*ptr = 5; // Assign value to allocated memory
free(ptr); // Free the allocated memory
e) Character Handling Functions (ctype.h)

The ctype.h library provides functions for checking and manipulating individual characters.

 Example Functions:

#include <ctype.h>

char ch = 'A';
if (isupper(ch)) { // Check if character is uppercase
printf("Uppercase\n");
}

27
ch = tolower(ch); // Convert to lowercase
f) Time Handling Functions (time.h)

The time.h library provides functions to handle time-related tasks.

 Example Functions:

#include <time.h>
time_t t = time(NULL); // Get current time
struct tm *tm_info = localtime(&t); // Convert to local time

printf("Current time: %s", asctime(tm_info)); // Print the local time


g) Error Handling Functions (errno.h)

The errno.h library defines macros and functions to handle errors.

 Example Functions:

#include <errno.h>
#include <stdio.h>
FILE *file = fopen("[Link]", "r");
if (file == NULL) {
perror("Error opening file"); // Prints the error message
printf("Error number: %d\n", errno); // Prints the error code

Common Data Type Conversions in C

From Type To Type Implicit Conversion Explicit Conversion

int float Yes Yes (int to float)

float int No Yes (float to int)

int double Yes Yes (int to double)

double int No Yes (double to int)

28
From Type To Type Implicit Conversion Explicit Conversion

char int Yes Yes (char to int)

int char No Yes (int to char)

Summary of Key Library Functions

 stdio.h: Functions for input and output (e.g., printf, scanf).


 math.h: Functions for mathematical calculations (e.g., sqrt, pow).
 string.h: Functions for string manipulation (e.g., strlen, strcpy).
 stdlib.h: Functions for memory allocation (e.g., malloc, free).
 ctype.h: Functions for character tests (e.g., isalpha, isdigit).
 time.h: Functions for handling time (e.g., time, localtime).

These functions and type conversions provide powerful tools to handle data and perform a
wide range of operations in C programs.

MANAGING INPUT AND OUTPUT FUNCTIONS

In C, managing input and output is done using functions provided by the stdio.h library.
These functions allow you to read data from the user (input) and display results (output).
Below is an explanation of the most commonly used input and output functions in C.

1. Output Functions in C (Printing Data)

Output functions are used to display data to the user. The most commonly used output
function is printf(), which provides formatted output.

a) printf() Function

 Purpose: Prints data to the standard output (usually the console).

29
Syntax

printf("format string", arguments);

Example

#include <stdio.h>

int main() {
int age = 25;
float salary = 35000.75;
char grade = 'A';

printf("Age: %d\n", age); // %d for integer


printf("Salary: %.2f\n", salary); // %.2f for floating-point
printf("Grade: %c\n", grade); // %c for character

return 0;
}

Explanation:

o %d: Used to print integers.


o %.2f: Used to print floating-point numbers with 2 decimal places.
o %c: Used to print characters.

b) puts() Function

 Purpose: Prints a string followed by a newline.

Syntax:

puts("string");

Example:

#include <stdio.h>

30
int main() {
puts("Hello, World!"); // Automatically adds a newline after the string
return 0;
}
c) putchar() Function

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

Syntax:

putchar(character);

Example

#include <stdio.h>

int main() {
putchar('A'); // Prints 'A'
return 0;
}

2. Input Functions in C (Reading Data)

Input functions are used to read data from the user. The most common input functions are
scanf(), getchar(), and gets(). However, gets() is unsafe, and it's better to avoid it in modern C
programming.

a) scanf() Function

 Purpose: Reads input from the user based on specified format.

Syntax:

scanf("format string", &variable);

31
Example:

#include <stdio.h>
int main() {
int age;
float salary;

printf("Enter your age: ");


scanf("%d", &age); // %d is for integer input

printf("Enter your salary: ");


scanf("%f", &salary); // %f is for float input

printf("Your age is: %d\n", age);


printf("Your salary is: %.2f\n", salary);

return 0;
}

Explanation:

o %d: Reads an integer.


o %f: Reads a floating-point number.
o The & (address-of) operator is used to pass the address of the variable to
scanf() so it can store the input.

b) getchar() Function

 Purpose: Reads a single character from the standard input

Syntax:

getchar();

32
Example:

#include <stdio.h>

int main() {
char ch;
printf("Enter a character: ");
ch = getchar(); // Reads a single character
printf("You entered: %c\n", ch);
return 0;
}
c) gets() Function (Deprecated, Not Recommended)

 Purpose: Reads a string of characters until a newline is encountered.

Syntax
gets(string);

Warning: The gets() function is unsafe because it can cause buffer overflow. It is
recommended to use fgets() instead.

Example:

#include <stdio.h>

int main() {
char name[50];

printf("Enter your name: ");


gets(name); // NOT SAFE - Avoid using this in modern C programming
printf("Your name is: %s\n", name);

return 0;
}

33
d) fgets() Function

 Purpose: Reads a line of text from a file or standard input (safer alternative to gets()).

Syntax:

fgets(string, size, stdin);

Example:

#include <stdio.h>

int main() {
char name[50];

printf("Enter your name: ");


fgets(name, sizeof(name), stdin); // Safer alternative to gets()
printf("Your name is: %s\n", name);

return 0;
}

Explanation:

o fgets() reads a string from the standard input (stdin), but you must specify the
buffer size to avoid buffer overflow.
o It includes the newline character \n in the string, so you may need to handle it
when processing the input.

[Link] input and output

a) Formatted Output with printf()

 Integer Format Specifiers:


o %d: Signed decimal integer.
o %u: Unsigned decimal integer.
o %x: Unsigned hexadecimal integer (lowercase).

34
o %X: Unsigned hexadecimal integer (uppercase).
 Floating-Point Format Specifiers:
o %f: Decimal floating-point number.
o %.2f: Floating-point number with 2 decimal places.
o %e: Scientific notation (e.g., 1.234000e+02).
o %g: Shorter of %f or %e format.

b) Formatted Input with scanf()

 Integer Format Specifiers:


o %d: Reads a signed decimal integer.
o %u: Reads an unsigned decimal integer.
o %x: Reads a hexadecimal integer (lowercase).
o %X: Reads a hexadecimal integer (uppercase).

 Floating-Point Format Specifiers:


o %f: Reads a decimal floating-point number.
o %lf: Reads a double precision floating-point number (though in scanf(), both
%f and %lf can be used for float).

4. Flushing Input/Output Buffers

In some cases, you might want to flush the output buffer to ensure all data is printed
immediately, especially in interactive applications.

a) fflush(stdout)

 Purpose: Flushes the output buffer.

Syntax:

fflush(stdout);

Example:

#include <stdio.h>

35
int main() {
printf("Please wait...");
fflush(stdout); // Forces the output to be displayed immediately
// Simulate a delay
for (int i = 0; i < 1000000000; i++) {} // Some computation
printf(" Done\n");
return 0;
}

Summary

 Output Functions:
o printf(): Formatted output to standard output (console).
o puts(): Output a string followed by a newline.
o putchar(): Output a single character.
 Input Functions:
o scanf(): Formatted input from standard input (keyboard).
o getchar(): Input a single character.
o fgets(): Safe function to input a string.
o gets(): Unsafe and deprecated function (avoid using it).

Managing input and output in C is fundamental for interacting with users and processing
data. Understanding these functions allows you to build more effective and interactive
programs.

FORMATTED AND UNFORMATTED I/O FUNCTIONS IN C

In C programming, Formatted and Unformatted I/O Functions are used to handle input
and output operations. Let’s explore both types with explanations and examples.

🔵 Formatted I/O Functions

These functions allow input and output operations in a specific format. They enable you to
control how data is read or displayed, including specifying data types and layout.

✅ Common Formatted I/O Functions:

36
Function Description

printf() Displays formatted output to the console

scanf() Takes formatted input from the user

fprintf() Writes formatted output to a file

fscanf() Reads formatted input from a file

sprintf() Stores formatted output in a string

sscanf() Reads formatted input from a string

🔧 Example of Formatted I/O:

#include <stdio.h>

int main() {
int age;
char name[50];

// Taking input using scanf


printf("Enter your name: ");
scanf("%s", name);

printf("Enter your age: ");


scanf("%d", &age);

// Displaying output using printf


printf("Hello %s, you are %d years old.\n", name, age);

return 0;
}

Output:

37
Enter your name: John
Enter your age: 25
Hello John, you are 25 years old.

🔵 Unformatted I/O Functions

These functions perform input and output operations without any specific format. They
handle data as raw bytes and are faster than formatted I/O functions because they don’t
perform format checks.

✅ Common Unformatted I/O Functions:

Function Description

getchar() Reads a single character from the keyboard

putchar() Displays a single character to the console

gets() Reads a string from the keyboard (deprecated)

puts() Displays a string to the console

fgets() Reads a string from a file or input stream

fputs() Writes a string to a file or output stream

🔧 Example of Unformatted I/O:

#include <stdio.h>

int main() {
char ch;
char str[50];

// Using getchar and putchar


printf("Enter a character: ");
ch = getchar();

38
printf("You entered: ");
putchar(ch);
printf("\n");

// Using gets and puts


printf("Enter a string: ");
gets(str); // Warning: 'gets' is unsafe and deprecated
puts("You entered:");
puts(str);

return 0;
}

Output:

Enter a character: A
You entered: A
Enter a string: Hello, World!
You entered:
Hello, World!

🔵 Key Differences Between Formatted and Unformatted I/O Functions:


Aspect Formatted I/O Unformatted I/O

Control Provides control over data type and format No control over data type or format

Speed Slower due to format checking Faster due to raw data handling

Functions printf(), scanf(), etc. getchar(), putchar(), etc.

Use Case Used for user-friendly I/O Used for faster, raw I/O

UNIT II

39
Decision Making in C

Decision-making in C allows a program to make decisions based on conditions and execute


different blocks of code accordingly. C provides several decision-making constructs like if,
else, switch, etc., to control the flow of the program.

Types of Conditional Statements in C


Following are the decision-making statements available in C:

 if Statement
 if-else Statement
 Nested if Statement
 if-else-if Ladder
 switch Statement
 Conditional Operator
 Jump Statements:
 break
 continue
 goto
 return
Let’s discuss each of them one by one.
1. if in C
The if statement is the most simple decision-making statement. It is used to decide whether
a certain statement or block of statements will be executed or not i.e if a certain condition is
true then a block of statements is executed otherwise not.
Syntax of if Statement
if(condition)
{
// Statements to execute if
// condition is true
}
Here, the condition after evaluation will be either true or false. C if statement accepts
boolean values – if the value is true then it will execute the block of statements below it
otherwise not. If we do not provide the curly braces ‘{‘ and ‘}’ after if(condition) then by

40
default if statement will consider the first immediately below statement to be inside its
block.

Flowchart of if Statement

Flow Diagram of if Statement

1. if Statement

The if statement executes a block of code only if the condition is true.

✅ Syntax:

if (condition) {
// Code to execute if condition is true
}

🔧 Example:

#include <stdio.h>

int main() {
int num = 10;

if (num > 0) {
printf("The number is positive.\n");
}
return 0;
}

41
2. if-else in C
The if statement alone tells us that if a condition is true it will execute a block of statements
and if the condition is false it won’t. But what if we want to do something else when the
condition is false? Here comes the C else statement. We can use the else statement with
the if statement to execute a block of code when the condition is false. The if-else
statement consists of two blocks, one for false expression and one for true expression.
Syntax of if else in C
✅ Syntax:
if (condition) {
// Code to execute if condition is true
} else {
// Code to execute if condition is false
}

Flowchart of if-else Statement

Flow Diagram of if else

🔧 Example:
#include <stdio.h>

int main() {

42
int num = -5;

if (num > 0) {
printf("The number is positive.\n");
} else {
printf("The number is not positive.\n");
}

return 0;
}
Output

i is greater than 15

The block of code following the else statement is executed as the condition present in
the if statement is false.

3. Nested if-else in C
A nested if in C is an if statement that is the target of another if statement. Nested if
statements mean an if statement inside another if statement. Yes, C allow us to nested if
statements within if statements, i.e, we can place an if statement inside another if statement.
✅ Syntax:
if (condition1) {
if (condition2) {
// Code to execute if both conditions are true
}
}

🔧 Example:
#include <stdio.h>

int main() {
int num = 15;

if (num > 0) {

43
if (num % 2 == 0) {
printf("The number is even.\n");
} else {
printf("The number is odd.\n");
}
}

return 0;
}
FLOW CHART:

✅ Syntax:
if (condition1) {
if (condition2) {
// Code to execute if both conditions are true
}
}

🔧 Example:
#include <stdio.h>

int main() {
int num = 15;

44
if (num > 0) {
if (num % 2 == 0) {
printf("The number is even.\n");
} else {
printf("The number is odd.\n");
}
}

return 0;
}

4. if-else-if Ladder in C
The if else if statements are used when the user has to decide among multiple options. The
C if statements are executed from the top down. As soon as one of the conditions
controlling the if is true, the statement associated with that if is executed, and the rest of the
C else-if ladder is bypassed. If none of the conditions is true, then the final else statement
will be executed. if-else-if ladder is similar to the switch statement.

Syntax of if-else-if Ladder


if (condition)
statement;
else if (condition)
statement;
.
.
else
statement;

Flowchart of if-else-if Ladder

45
Flow Diagram of if-else-if

✅ Syntax:
if (condition1) {
// Code to execute if condition1 is true
} else if (condition2) {
// Code to execute if condition2 is true
} else {
// Code to execute if none of the conditions are true
}
🔧 Example:
#include <stdio.h>
int main() {
int num = 0;
if (num > 0) {
printf("The number is positive.\n");
} else if (num < 0) {
printf("The number is negative.\n");
} else {
printf("The number is zero.\n");
}
return 0;}

46
5. switch Statement in C
The switch case statement is an alternative to the if else if ladder that can be used to execute
the conditional code based on the value of the variable specified in the switch statement.
The switch block consists of cases to be executed based on the value of the switch variable.
Syntax of switch
switch (expression) {
case value1:
statements;
case value2:
statements;
....
....
....
default:
statements;
}
Flowchart of switch

47
🔧 Example:
#include <stdio.h>
int main() {
int day = 3;
switch (day) {
case 1:
printf("Monday\n");
break;
case 2:
printf("Tuesday\n");
break;
case 3:
printf("Wednesday\n");
break;
default:
printf("Invalid day\n");
}
return 0;
}

6. Conditional Operator in C
The conditional operator is used to add conditional code in our program. It is similar to the
if-else statement. It is also known as the ternary operator as it works on three operands.

Syntax of Conditional Operator


(condition) ? [true_statements] : [false_statements];

48
Flowchart of Conditional Operator

🔧 Example:
#include <stdio.h>
int main() {
int num = 5;
// Using conditional operator
num > 0 ? printf("Positive number\n") : printf("Non-positive number\n");
return 0;
}
7. Jump Statements in C
These statements are used in C for the unconditional flow of control throughout the
functions in a program. They support four types of jump statements:

In C programming, the keywords break, continue, goto, and return are control flow
statements used to manage the flow of a program. Here's a detailed explanation of each:

1. break

 The break statement is used to exit a loop or switch statement prematurely.


 When break is encountered inside a loop (like for, while, or do-while), it immediately
terminates the loop and the program continues with the next statement after the loop.
 It can also be used to exit a switch case.

49
Example:

for (int i = 0; i < 5; i++) {


if (i == 3) {
break; // Exits the loop when i equals 3
}
printf("%d\n", i);
}
// Output: 0 1 2

2. continue

 The continue statement is used to skip the current iteration of a loop and proceed to
the next iteration.
 When encountered, it skips the remaining code in the current loop body and moves to
the next iteration, if any.

Example:

for (int i = 0; i < 5; i++) {


if (i == 3) {
continue; // Skips the iteration when i equals 3
}
printf("%d\n", i);
}
// Output: 0 1 2 4

3. goto

 The goto statement provides a way to transfer control unconditionally to another part
of the program.
 It is typically used with labels to create loops or jump over certain sections of code.
 Note: The use of goto is generally discouraged, as it can make code harder to
understand and maintain.

50
Example:

int i = 0;
start: // Label
if (i < 5) {
printf("%d\n", i);
i++;
goto start; // Jumps to 'start' label, continuing the loop
}
// Output: 0 1 2 3 4

4. return

 The return statement is used to exit a function and optionally return a value to the
caller.
 If the function has a return type (e.g., int, float), return can return a value of that type;
otherwise, it simply terminates the function.
 In main(), return 0; is commonly used to indicate successful execution.

Example:

int add(int a, int b)

return a + b; // Returns the sum of a and b to the caller


}

int main()
{
int result = add(3, 4); // Calls add() function
printf("%d\n", result); // Output: 7
return 0; // Exits the main function and returns control to the OS
}

51
LOOPING

In C, loops are used to repeat a block of code multiple times. The main types of loops in C
are:

1. for Loop

 The for loop is used when you know in advance how many times you want to repeat a
block of code.
 It has three parts: initialization, condition, and increment/decrement.

Syntax:
for (initialization; condition; increment/decrement) {
// Code to be executed
}

Example:

for (int i = 0; i < 5; i++){

printf("%d\n", i);
}
// Output: 0 1 2 3 4

Explanation:

 Initialization: Sets the initial value of the loop variable (e.g., int i = 0).
 Condition: Specifies the condition that must be true for the loop to continue (e.g., i <
5).
 Increment/Decrement: Increases or decreases the loop variable (e.g., i++).

52
for loop Equivalent Flow Diagram:

2. while Loop

 The while loop is used when the number of iterations is not known in advance, and
the loop should run as long as a specified condition is true.
 The condition is checked before each iteration.

Syntax:

while (condition) {
// Code to be executed

Example:

int i = 0;
while (i < 5) {
printf("%d\n", i);
i++;
}

53
// Output: 0 1 2 3 4

Explanation:

 The loop continues as long as the condition (i < 5) is true. After each iteration, the
value of i is incremented.

Flow Diagram for while loop:

3. do-while Loop

 The do-while loop is similar to the while loop, except that the condition is checked
after each iteration. This guarantees that the loop runs at least once.

Syntax:

do {
// Code to be executed

} while (condition);

Example:

int i = 0;
do {
printf("%d\n", i);
i++;

54
} while (i < 5);
// Output: 0 1 2 3 4

Explanation:

 The code block inside the do part is executed once, then the condition (i < 5) is
checked. If the condition is true, the loop continues.

Key Differences:

 for loop: Best when the number of iterations is known in advance. Initialization,
condition, and increment/decrement are all in one line.
 while loop: Ideal when the number of iterations is not known and depends on some
dynamic condition.
 do-while loop: Ensures the loop executes at least once, since the condition is checked
after the loop body.

55
FUNCTIONS

FUNCTION DEFINITION:

In C, a function is a block of code that performs a specific task. Functions are used to break
down complex programs into smaller, manageable parts. Defining and using functions in C
follows a specific syntax. Here’s a detailed explanation:

1. Function Definition

A function definition consists of:

 Return type: The type of data the function will return (e.g., int, float, void).
 Function name: The name by which the function is called.
 Parameters (optional): Input values passed to the function.
 Function body: A block of statements that define what the function does.

Syntax:
return_type function_name(parameter_list) {
// Function body
// Code to be executed
}

[Link] Declaration (Prototype)

Before you define a function, you can declare it to let the compiler know its name, return
type, and parameters. The declaration can be placed at the beginning of the program or before
the function is called.

Syntax:

return_type function_name(parameter_list);

Example:

int add (int, int); // Function prototype

56
3. Function Definition Example

Let’s go through an example of defining a simple function.

Example:

#include <stdio.h>
// Function declaration
int add(int, int); // Declares that a function named 'add' returns an int and takes two int
parameters
// Function definition
int add(int a, int b) {
return a + b; // Returns the sum of a and b
}
int main() {
int result = add(3, 4); // Calls the add function
printf("Sum: %d\n", result); // Output: Sum: 7
return 0;
}

Explanation of the Example:

1. Function Declaration:
o The prototype int add(int, int); informs the compiler that a function named add
exists, returns an int, and takes two int parameters. This declaration can be
used before the main function if the function definition is written later in the
program.

2. Function Definition:
o The function int add(int a, int b) is defined to take two integer parameters and
return their sum.

3. Function Call:
o Inside main(), the add(3, 4) function call invokes the function and passes 3 and
4 as arguments. The result is stored in the variable result, which is then
printed.

57
4. Function with void Return Type

If a function does not return a value, you use void as the return type.

EXAMPLE

#include <stdio.h>

// Function declaration

void printMessage();

// Function definition
void printMessage() {
printf("Hello, World!\n");
}
int main()
{
printMessage(); // Calls the function to print the message
return 0;
}

 In this example, the printMessage() function has a void return type because it does not
return any value. It simply prints a message to the screen.

5. Passing Arguments to Functions

You can pass arguments (values) to functions by:

 Call by value: A copy of the value is passed to the function.


 Call by reference: A reference to the original variable is passed, allowing the
function to modify the variable.

Example (Call by Value):

void modifyValue(int a) {
a = 10; // This modification only affects the local copy of a

58
}
int main() {
int num = 5;
modifyValue(num);
printf("num = %d\n", num); // Output: num = 5
return 0;
}

Example (Call by Reference):

void modifyValue(int *a) {


*a = 10; // This modification affects the original value of num
}
int main() {
int num = 5;
modifyValue(&num); // Passing the address of num
printf("num = %d\n", num); // Output: num = 10
return 0;
}

Recursive function

Recursion is the process of a function calling itself repeatedly till the given condition is
satisfied. A function that calls itself directly or indirectly is called a recursive function and
such kind of function calls are called recursive calls.

The basic syntax structure of the recursive functions is:


type function_name (args) {
// function statements
// base condition
// recursion case (recursive call)
}
EXAMPLE:
int factorial(int n) {
if (n == 0) {

59
return 1;
}
return n * factorial(n - 1);
}

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

60
UNIT III

ARRAYS

DEFINITION

An Array is a collection of elements of the same type stored in contiguous memory


locations. The size of the array must be specified during declaration, and arrays in C have a
fixed size once defined.

Declaring an Array in C

data_type array_name[array_size];

 data_type: Type of the elements (e.g., int, char, float).


 array_name: The name of the array.
 array_size: The number of elements the array can hold (must be a constant).

Example of Array Declaration

int numbers[5]; // Declaring an integer array of size 5

Here, the array numbers can hold 5 integer values, and the index range will be from 0 to 4.

Initializing Arrays

Arrays can be initialized at the time of declaration.

1. Static Initialization:

int numbers[5] = {1, 2, 3, 4, 5};

2. Partial Initialization: If you initialize fewer elements, the remaining ones are set to
zero.

int numbers[5] = {1, 2}; // numbers = {1, 2, 0, 0, 0}

3. Implicit Size: You can omit the size, and the compiler will determine it based on the
number of elements.

61
int numbers[] = {1, 2, 3, 4, 5}; // Array size will be automatically set to 5
In C, an array is a collection of elements of the same type stored in contiguous memory
locations. This organization allows efficient access to elements using their index. Arrays
can also be of different types depending upon the direction/dimension they can store the
elements. It can be 1D, 2D, 3D, and more. We generally use only one-dimensional, two-
dimensional, and three-dimensional arrays.
In this article, we will learn all about one-dimensional (1D) arrays in C, and see how to use
them in our C program.

One Dimensional Arrays in C


A one-dimensional array can be viewed as a linear sequence of elements. We can only
increase or decrease its size in a single direction.

Only a single row exists in the one-dimensional array and every element within the array is
accessible by the index. In C, array indexing starts zero-indexing i.e. the first element is at
index 0, the second at index 1, and so on up to n-1 for an array of size n.
In declaration, we specify then name and the size of the 1d array.

1D Array Declaration Syntax

elements_type array_name[array_size];

This initialization only works when performed with declaration.

62
1D Array Element Accessing/Updating Syntax
After the declaration, we can use the index of the element along with the array name to
access it.
array_name [index]; // accessing the element

Then, we can also assign the new value to the element using assignment operator.

array_name [index] = new_value; // updating element

Example:
#include <stdio.h>

int main()

// declaring and initializing array

int arr[5] = { 1, 2, 4, 8, 16 };

// printing it

for (int i = 0; i < 5; i++) {

printf("%d ", arr[i]);

63
printf("\n");

// updating elements

arr[3] = 9721;

// printing again

for (int i = 0; i < 5; i++) {

printf("%d ", arr[i]);

return 0;

Output
1 2 4 8 16

1 2 4 9721 16

A multi-dimensional array can be defined as an array that has more than one dimension.
Having more than one dimension means that it can grow in multiple directions. Some
popular multidimensional arrays are 2D arrays and 3D arrays. In this article, we will learn
about multidimensional arrays in C programming language.
Syntax

The general form of declaring N-dimensional arrays is shown below:


type arr_name[size1][size2]….[sizeN];

 type: Type of data to be stored in the array.


 arr_name: Name assigned to the array.
 size1, size2,…, sizeN: Size of each dimension.
Examples
Two-dimensional array: int two_d[10][20];

Three-dimensional array: int three_d[10][20][30];

64
Types of Multidimensional Arrays
In C, there can be many types of arrays depending on their dimensions but two of them are
most commonly used:
1. Two-Dimensional Array (2D Array)
2. Three-Dimensional Array (3D Array)

Two-Dimensional (2D) Arrays in C


A two-dimensional array or 2D array is the simplest form of the multidimensional array.
We can visualize a two-dimensional array as one-dimensional arrays stacked vertically
forming a table with ‘m’ rows and ‘n’ columns. In C, arrays are 0-indexed, so the row
number ranges from 0 to (m-1) and the column number ranges from 0 to (n-1).
Declaration of 2D Array

A 2D array with m rows and n columns can be created as:


type arr_name[m][n];
where,
 type: Type of data to be stored in each element.
 arr_name: Name assigned to the array.
 m: Number of rows.
 n: Number of columns.
For example, we can declare a two-dimensional integer array with name ‘arr’ with 10 rows
and 20 columns as:
int arr[10][20];
Initialization of 2D Arrays
We can initialize a 2D array by using a list of values enclosed inside ‘{ }’ and separated by
a comma as shown in the example below:
int arr[3][4] = {0, 1 ,2 ,3 ,4 , 5 , 6 , 7 , 8 , 9 , 10 , 11}
or
int arr[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};
The elements will be stored in the array from left to right and top to bottom. So, the first 4
elements from the left will be filled in the first row, the next 4 elements in the second row,
and so on. This is clearly shown in the second syntax where each set of inner braces
represents one row.

65
In list initialization, we can skip specifying the size of the row. The compiler will
automatically deduce it in this case. So, the below declaration is valid.
type arr_name[][n] = {…values…};

// C Program to illustrate the 2D array

#include <stdio.h>

int main() {

// Create and initialize an array with 3 rows

// and 2 columns

int arr[3][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };

// Print each array element's value

for (int i = 0; i < 3; i++) {

for (int j = 0; j < 2; j++) {

printf("arr[%d][%d]: %d ", i, j, arr[i][j]);

printf("\n");

return 0;
}
Output

arr[0][0]: 0 arr[0][1]: 1

arr[1][0]: 2 arr[1][1]: 3

arr[2][0]: 4 arr[2][1]: 5

66
Three-Dimensional (3D) Array in C
A Three-Dimensional Array or 3D array in C is a collection of two-dimensional arrays. It
can be visualized as multiple 2D arrays stacked on top of each other.

Declaration of 3D Array in C

We can declare a 3D array with x 2D arrays each having m rows and n columns using

the syntax shown below:


type arr_name[x][m][n];

 type: Type of data to be stored in each element.


 arr_name: name of the array
 x: Number of 2D arrays. (also called depth of the array)
 m: Number of rows in each 2D array.
 n: Number of columns in each 2D array.
For example,
int arr[2][2][2]

Initialization of 3D Array in C
Initialization in a 3D array is the same as that of 2D arrays. The difference is as the number
of dimensions increases so the number of nested braces will also increase.
int arr[2][3][2] = {0, 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10, 11}
or
int arr[2][3][2] = { { { 1, 1 }, { 2, 3 }, { 4, 5 } },
{ { 6, 7 }, { 8, 9 }, { 10, 11 } } };
Example
#include <stdio.h>

int main() {

// Create and Initialize the 3-dimensional array

int arr[2][3][2] = { { { 1, 1 }, { 2, 3 }, { 4, 5 } },

{ { 6, 7 }, { 8, 9 }, { 10, 11 } } };

// Loop through the depth

67
for (int i = 0; i < 2; ++i) {

// Loop through the rows of each depth

for (int j = 0; j < 3; ++j) {

// Loop through the columns of each row

for (int k = 0; k < 2; ++k)

printf("arr[%i][%i][%i] = %d ", i, j, k,

arr[i][j][k]);

printf("\n");

printf("\n\n");

return 0;

Output
arr[0][0][0] = 1 arr[0][0][1] = 1

arr[0][1][0] = 2 arr[0][1][1] = 3

arr[0][2][0] = 4 arr[0][2][1] = 5

arr[1][0][0] = 6 arr[1][0][1] = 7

arr[1][1][0] = 8 arr[1][1][1] = 9

arr[1][2][0] = 10 arr[1][2][1] = 11

68
Passing Arrays to Functions in C

In C, when you pass an array to a function, you are actually passing a pointer to the first
element of the array. This allows the function to modify the original array.

🔑 Important Points to Remember:

1. Arrays are always passed by reference in C.


2. You need to pass the size of the array as an additional parameter since arrays don't
carry size information.
3. Any changes made to the array inside the function will reflect in the original array.

✅ Example 1: Passing an Array to a Function

Here's a simple example that shows how to pass an array to a function in C:

#include <stdio.h>

// Function to print elements of an array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

int main() {
int myArray[] = {10, 20, 30, 40, 50};
int size = sizeof(myArray) / sizeof(myArray[0]);

printf("Array elements: ");


printArray(myArray, size);

return 0;
}

69
💻 Output
Array elements: 10 20 30 40 50
Definition of a String

A string in C is a sequence of characters that is terminated by a null character ('\0'). The


null character indicates the end of the string.

In C, strings are essentially arrays of characters, and the '\0' character is automatically added
at the end to mark the string's termination.

✅ String Syntax in C

char str[] = "Hello"; // Implicit null character at the end

🔑 Key Points About Strings in C

1. Strings are stored as arrays of characters.


2. The null character ('\0') is used to mark the end of the string.
3. C does not have a built-in string data type like other languages; you use character
arrays or pointers.
4. Strings are mutable (you can modify their contents).

✅ String Declaration and Initialization

There are two ways to declare and initialize a string:

1️⃣ Using a character array:

char str1[] = "Hello, World!";

2️⃣ Using a pointer to a string:

char *str2 = "Hello, World!";

✅ Example: Printing a String

#include <stdio.h>

int main() {

70
char str[] = "Hello, World!";
printf("%s\n", str); // %s is the format specifier for strings
return 0;
}
💻 Output:
Hello, World!

✅ String Input and Output

Use the scanf() and printf() functions for string input and output.

#include <stdio.h>

int main() {
char name[50]; // Allocate memory for the string

printf("Enter your name: ");


scanf("%s", name); // Takes input until a space is encountered

printf("Hello, %s!\n", name);

return 0;
}
💻 Output:
Enter your name: John
Hello, John!

📚 Operations on Strings in C

In C, string operations involve manipulating character arrays. These operations include


calculating the length of a string, copying one string to another, concatenating strings,
comparing strings, and more. Most of these operations are available through functions in the
<string.h> library.

Here’s a detailed guide to common string operations in C with examples.

71
🔧 Common String Operations:
Operation Function Description

Length strlen() Finds the length of the string.

Copy strcpy() Copies one string to another.

Concatenation strcat() Joins two strings.

Comparison strcmp() Compares two strings.

Finding a character strchr() Finds the first occurrence of a character.

Finding a substring strstr() Finds the first occurrence of a substring.

Reversing a string Custom function Reverses the given string.

✅ 1. Finding the Length of a String (strlen)

The strlen() function calculates the number of characters in a string, excluding the null
terminator ('\0').

Example:

#include <stdio.h>
#include <string.h>

int main() {
char str[] = "Hello, World!";
int length = strlen(str);

printf("Length of the string: %d\n", length);


return 0;
}
💻 Output:
Length of the string: 13

72
✅ 2. Copying a String (strcpy)

The strcpy() function copies the content of one string to another.

Example:

#include <stdio.h>
#include <string.h>

int main() {
char source[] = "Hello, World!";
char destination[50];

strcpy(destination, source);

printf("Copied string: %s\n", destination);


return 0;
}
💻 Output:
Copied string: Hello, World!

✅ 3. Concatenating Two Strings (strcat)

The strcat() function joins two strings by appending the second string to the first.

Example:

#include <stdio.h>
#include <string.h>

int main() {
char str1[50] = "Hello, ";
char str2[] = "World!";

strcat(str1, str2);

73
printf("Concatenated string: %s\n", str1);
return 0;
}
💻 Output:

Concatenated string: Hello, World!

✅ 4. Comparing Two Strings (strcmp)

The strcmp() function compares two strings lexicographically.

 Returns 0 if both strings are equal.


 Returns a negative value if the first string is less than the second.
 Returns a positive value if the first string is greater than the second.

Example:

#include <stdio.h>
#include <string.h>

int main() {
char str1[] = "Hello";
char str2[] = "World";

int result = strcmp(str1, str2);

if (result == 0) {
printf("Strings are equal.\n");
} else if (result < 0) {
printf("String 1 is less than String 2.\n");
} else {
printf("String 1 is greater than String 2.\n");
}

74
return 0;
}
💻 Output:
String 1 is less than String 2.

✅ 5. Finding a Character in a String (strchr)

The strchr() function returns a pointer to the first occurrence of a character in a string.

Example:

#include <stdio.h>

#include <string.h>
int main() {
char str[] = "Hello, World!";
char *ptr = strchr(str, 'W');

if (ptr != NULL) {
printf("Character found: %c\n", *ptr);
} else {
printf("Character not found.\n");
}
return 0;
}
💻 Output:
Character found: W

✅ 6. Finding a Substring in a String (strstr)

The strstr() function returns a pointer to the first occurrence of a substring in a string.

Example:

#include <stdio.h>

75
#include <string.h>
int main() {
char str[] = "Hello, World!";
char *ptr = strstr(str, "World");

if (ptr != NULL) {
printf("Substring found: %s\n", ptr);
} else {
printf("Substring not found.\n");
}
return 0;
}
💻 Output:
Substring found: World!
✅ 7. Reversing a String (Custom Function)

There is no built-in function to reverse a string in C, but you can create a custom function.

Example:

#include <stdio.h>
#include <string.h>
// Function to reverse a string
void reverseString(char str[]) {
int length = strlen(str);
for (int i = 0; i < length / 2; i++) {
char temp = str[i];
str[i] = str[length - i - 1];
str[length - i - 1] = temp;
}
}
int main() {
char str[] = "Hello, World!";
reverseString(str);

76
printf("Reversed string: %s\n", str);
return 0;
}
💻 Output:
Reversed string: !dlroW ,olleH

✅ 8. Converting Strings to Upper/Lower Case (strupr() / strlwr())

These functions are not part of the standard C library but are available in some compilers.

Example:

#include <stdio.h>
#include <string.h>

// Custom function to convert to uppercase


void toUpperCase(char str[]) {
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
str[i] = str[i] - 32;
}
}
}

int main() {
char str[] = "hello, world!";
toUpperCase(str);

printf("Uppercase string: %s\n", str);


return 0;
}
💻 Output:
Uppercase string: HELLO, WORLD!

77
📚 Arrays of Strings in C

In C, an array of strings is essentially a two-dimensional array where each row is a string (a


character array). This structure allows you to store multiple strings in a single variable.

For example, an array of strings can store a list of names, words, or sentences.

✅ Declaration of an Array of Strings

There are two ways to declare an array of strings:

1️⃣ Fixed-size 2D character array:


Each string has a fixed maximum length.

char names[3][20] = {
"Alice",
"Bob",
"Charlie"
};

2️⃣ Array of pointers to strings:


Strings can have variable lengths.

char *names[] = {
"Alice",
"Bob",
"Charlie"
};

🔧 1. Using a Fixed-size 2D Array

This is a straightforward way to declare an array of strings.

Example:

#include <stdio.h>
int main() {

78
// Array of 3 strings, each with a maximum length of 19 characters
char names[3][20] = {
"Alice",
"Bob",
"Charlie"
};
printf("Names are:\n");
for (int i = 0; i < 3; i++) {
printf("%s\n", names[i]);
}
return 0;
}
💻 Output:
Names are:
Alice
Bob
Charlie

📚 Passing Strings to Functions in C

In C, you can pass strings to functions in two primary ways:

1. By passing a character array (string)


2. By passing a pointer to a string

Both methods allow you to manipulate or process the string inside the function. Since strings
are arrays in C, they are always passed by reference, meaning any changes made to the string
inside the function will affect the original string.

✅ Method 1: Passing a String as a Character Array

You can pass a string to a function by declaring the parameter as a character array.

Example:

#include <stdio.h>

79
// Function to print a string
void printString(char str[]) {
printf("The string is: %s\n", str);
}

int main() {
char myString[] = "Hello, World!";
printString(myString); // Passing the string to the function
return 0;
}
💻 Output:
The string is: Hello, World!
✅ Method 2: Passing a String as a Pointer

You can also pass a string to a function using a pointer to a character array.

Example:

#include <stdio.h>
// Function to print a string using a pointer
void printString(char *str) {
printf("The string is: %s\n", str);
}
int main() {
char myString[] = "Hello, World!";
printString(myString); // Passing the string to the function
return 0;
}
💻 Output:
The string is: Hello, World!

📚 Storage Classes in C

A storage class in C defines the scope, visibility, lifetime, and default initial value of a
variable. There are four types of storage classes in C:

80
1. Automatic (auto)
2. External (extern)
3. Static (static)
4. Register (register)

1. auto (Automatic Storage Class)

 Default storage class for local variables.


 Variables are created when the function is called and destroyed when the function
exits.
 Scope: Local to the block in which it is defined.
 Lifetime: Exists only during the function execution.
 Default Value: Garbage (uninitialized).

✅ Example:

#include <stdio.h>
void display() {
auto int x = 10; // `auto` keyword is optional
printf("x = %d\n", x);
}
int main() {
display();
return 0;
}
2. extern (External Storage Class)

 Used to declare a global variable or function that is defined in another file.


 Makes the variable or function accessible across multiple files.
 Scope: Global.
 Lifetime: Exists throughout the program's execution.
 Default Value: 0.

✅ Example:

#include <stdio.h>

81
int count = 10; // Global variable

void display() {
printf("Count = %d\n", count);
}
3. static (Static Storage Class)

 Preserves the value of a variable across function calls.


 Scope: Local to the block in which it is defined (for local variables).
 Lifetime: Exists throughout the program's execution.
 Default Value: 0.

✅ Example:

#include <stdio.h>
void countCalls() {
static int count = 0; // Static variable
count++;
printf("Function called %d times\n", count);
}
int main() {
countCalls();
countCalls();
countCalls();
return 0;
}

Output:

Function called 1 times


Function called 2 times
Function called 3 times

82
4. register (Register Storage Class)

 Suggests that the variable be stored in the CPU register for faster access.
 Used for frequently accessed variables.
 Scope: Local to the block in which it is defined.
 Lifetime: Exists only during the function execution.
 Default Value: Garbage (uninitialized).
 Cannot be used with the & operator (because it may not have a memory address).

✅ Example:

#include <stdio.h>

int main() {
register int i;
for (i = 0; i < 5; i++) {
printf("%d ", i);
}
return 0;
}

Output:

01234
Storage Classes in C
Storage Class Scope Lifetime Default Value Keyword

auto Local Till the function ends Garbage auto

extern Global Entire program execution 0 extern

static Local/Global Entire program execution 0 static

register Local Till the function ends Garbage register

83
Stuctures

📚 Definition of Structures in C

A structure in C is a user-defined data type that allows you to group different types of
variables under a single name. It is used to represent a record or complex data that requires
multiple attributes, like storing information about a student, employee, or product.

Syntax of Structure

struct structure_name {
data_type member1;
data_type member2;
...

};

Example: Defining and Using a Structure

#include <stdio.h>
// Defining a structure
struct Student {
int id;
char name[50];
float marks;
};

int main() {
// Declaring a structure variable
struct Student s1;
// Assigning values to the structure members
[Link] = 101;
strcpy([Link], "Alice");
[Link] = 95.5;
// Printing structure members
printf("ID: %d\n", [Link]);

84
printf("Name: %s\n", [Link]);
printf("Marks: %.2f\n", [Link]);
return 0;
}

📚 Nested Structures in C

A nested structure is a structure within another structure. It allows you to group related data
together, even if the data has a more complex relationship. This is useful when representing

Syntax of Nested Structure

struct Outer {
data_type member1;
struct Inner {
data_type member2;
data_type member3;
} inner_var;

};

Example 1: Nested Structure

#include <stdio.h>

// Defining a nested structure


struct Address {
char city[50];
int zip;
};
struct Student {
int id;
char name[50];
struct Address address;
};
int main() {

85
// Declaring and initializing a structure variable
struct Student s1 = {101, "Alice", {"New York", 10001}};
// Accessing members of the nested structure
printf("ID: %d\n", [Link]);
printf("Name: %s\n", [Link]);
printf("City: %s\n", [Link]);
printf("ZIP: %d\n", [Link]);
return 0;
}
💻 Output:
ID: 101
Name: Alice
City: New York
ZIP: 10001

📚 Array of Structures in C

An array of structures allows you to store multiple structures of the same type in a
contiguous block of memory. This is useful when you want to manage a collection of similar
data, such as a list of students, employees, or products.

✅ Syntax of Array of Structures

struct StructureName {
data_type member1;
data_type member2;
...
};

struct StructureName array_name[size];

 size: The number of structures in the array.

StructureName: The name of the structure.

🔧 Example: Array of Structures

86
#include <stdio.h>

// Defining the structure


struct Student {
int id;
char name[50];
float marks;
};
int main() {
// Declaring an array of structures
struct Student students[3];
// Initializing the array of structures
students[0].id = 101;
strcpy(students[0].name, "Alice");
students[0].marks = 85.5;
students[1].id = 102;
strcpy(students[1].name, "Bob");
students[1].marks = 92.3;

students[2].id = 103;
strcpy(students[2].name, "Charlie");
students[2].marks = 78.9;
// Printing the details of each student
for (int i = 0; i < 3; i++) {
printf("Student %d: ID = %d, Name = %s, Marks = %.2f\n",
i + 1, students[i].id, students[i].name, students[i].marks);
}
return 0;
}
💻 Output:
Student 1: ID = 101, Name = Alice, Marks = 85.50
Student 2: ID = 102, Name = Bob, Marks = 92.30
Student 3: ID = 103, Name = Charlie, Marks = 78.90

87
📚 Passing Structures to Functions in C

You can pass a structure to a function in C in two ways:

1. By Value: The function receives a copy of the structure.


2. By Reference (using Pointers): The function receives a pointer to the structure,
allowing it to modify the original structure.

✅ 1. Passing Structure by Value

When you pass a structure by value, the function works with a copy of the structure, so any
changes made inside the function won't affect the original structure.

Example:

#include <stdio.h>
// Define a structure
struct Student {
int id;
char name[50];
};

// Function that takes structure by value


void display(struct Student s) {
printf("Student ID: %d\n", [Link]);
printf("Student Name: %s\n", [Link]);
}
int main() {
struct Student s1 = {101, "Alice"};
// Passing structure by value
display(s1);
return 0;
}
💻 Output:
Student ID: 101

88
Student Name: Alice

In this example, the structure s1 is passed to the display function, but it is not modified
within the function.

📚 Unions in C

A union is a user-defined data type in C that allows you to store different types of data in
the same memory location. Unlike structures, where each member has its own memory
space, all members of a union share the same memory. This means that a union can only
hold one value at a time, and the memory size is determined by the largest member.

🔧 Syntax of a Union

union UnionName {
data_type member1;
data_type member2;
...
};

 UnionName: The name of the union.

member1, member2, ...: Members of the union, which can have different data types.

✅ Example of Union

#include <stdio.h>
// Defining a union
union Data {
int i;
float f;
char c;
};
int main() {
// Declaring a variable of union type
union Data data;

89
// Assigning value to an integer member
data.i = 10;
printf("Data (int): %d\n", data.i);
// Assigning value to a float member (overwrites the previous value)
data.f = 3.14;
printf("Data (float): %.2f\n", data.f);
// Assigning value to a char member (overwrites the previous value)
data.c = 'A';
printf("Data (char): %c\n", data.c);
return 0;}
💻 Output:
Data (int): 10
Data (float): 3.14
Data (char): A

typedef in C

The typedef keyword in C is used to create type aliases. It allows you to define a new name
for an existing data type, making code more readable and easier to maintain. This is
particularly useful for complex data types like structures, pointers, or function pointers.

🔧 Syntax of typedef

typedef existing_type new_type_name;

 existing_type: The type you want to create an alias for.

new_type_name: The alias name you want to use for the existing type.
Example:
#include <stdio.h>

typedef int Integer; // Creating an alias for 'int'


typedef float Float; // Creating an alias for 'float'

int main() {

90
Integer num1 = 10; // Using 'Integer' as alias for 'int'
Float num2 = 3.14; // Using 'Float' as alias for 'float'

printf("Integer: %d\n", num1);


printf("Float: %.2f\n", num2);

return 0;
}
💻 Output

Integer: 10

Float: 3.14

📚 enum in C

An enum (short for "enumeration") is a user-defined data type in C that allows you to
assign names to integral constants, making your code more readable and easier to maintain. It
defines a set of named integer constants.

🔧 Syntax of enum

enum EnumName {
Name1 = value1,
Name2 = value2,
...
};

 EnumName: The name of the enum type.


 Name1, Name2, ...: The enumerators (named constants).

value1, value2, ...: The values assigned to each enumerator (optional). By default, the first
enumerator gets 0, the next gets 1, and so on.

✅ Example: Basic Enum

91
#include <stdio.h>
// Defining an enum
enum Weekday {
Sunday, // 0
Monday, // 1
Tuesday, // 2
Wednesday, // 3
Thursday, // 4
Friday, // 5
Saturday // 6
};
int main() {
enum Weekday today = Wednesday; // Assigning an enum value

printf("Today is: %d\n", today); // Printing the enum's integer value


return 0;
}
💻 Output:
Today is: 3

Here, Wednesday is automatically assigned the value 3, because enums are assigned values
starting from 0 by default.

Bit Fields in C

A bit field is a feature in C that allows you to specify the exact number of bits used to store a
variable within a structure. This can be useful for saving memory, especially when dealing
with flags or small numbers, where you don't need the full range of an int or char.

🔧 Syntax of Bit Fields

struct {
type member_name : bit_count;
};

92
 type: The data type of the field (usually int or unsigned).

member_name: The name of the bit field.

 bit_count: The number of bits allocated to the field.

✅ Example of Bit Fields

#include <stdio.h>
struct Employee {
unsigned int id : 4; // 4 bits for ID (0-15)
unsigned int age : 7; // 7 bits for age (0-127)
unsigned int salary : 10; // 10 bits for salary (0-1023)
};

int main() {
struct Employee emp1;
// Assigning values to bit fields
[Link] = 5;
[Link] = 30;
[Link] = 500;
// Printing the values of the bit fields
printf("ID: %u\n", [Link]); // Output: 5
printf("Age: %u\n", [Link]); // Output: 30
printf("Salary: %u\n", [Link]); // Output: 500
return 0;
}
💻 Output:
ID: 5
Age: 30
Salary: 500

In this example:

93
 id is allocated 4 bits (max value 15),
 age is allocated 7 bits (max value 127),
 salary is allocated 10 bits (max value 1023).

Difference between structure and union

Aspect Structure Union


Each member of the structure gets its All members of the union share the
Memory
own memory space. The total size is the same memory space. The total size is
Allocation
sum of the sizes of all the members. the size of the largest member.
Unions are more memory efficient
Memory Structures use more memory because
because they store only one member's
Usage each member gets its own memory.
value at a time.
A structure can store values of all its A union can store only one of its
Storage
members at the same time. members at any given time.
You can access only the last assigned
Access to You can access all members at once
member's value (the others may be
Members (their values are independent).
overwritten).
Useful when you need to store
Useful when you need to store different
different types of data but only need
Use Cases types of data together and need to
one value at a time (e.g., flags, control
access them independently.
bits).
Size is the sum of all members Size is the size of the largest member
Size
(including padding for alignment). (no padding required).

94
UNIT IV

📚 Pointers in C

A pointer is a variable that stores the memory address of another variable. Pointers are a
powerful feature in C that allow for dynamic memory management, direct memory access,
and more flexible data structures like linked lists.

🔧 Syntax of Pointers

type *pointer_name;

 type: The type of data the pointer is pointing to (e.g., int, float, etc.).

*: The asterisk (*) indicates that the variable is a pointer.

 pointer_name: The name of the pointer variable.

✅ Basic Pointer Example

#include <stdio.h>

int main() {
int num = 10; // Declare an integer variable
int *ptr = &num; // Declare a pointer that stores the address of 'num'

95
printf("Value of num: %d\n", num); // Output the value of num
printf("Address of num: %p\n", &num); // Output the memory address of num
printf("Pointer value (address stored in ptr): %p\n", ptr); // Address stored in ptr
printf("Dereferenced pointer value: %d\n", *ptr); // Dereferencing the pointer to get the
value of num

return 0;
}
💻 Output:
Value of num: 10
Address of num: 0x7ffee6f93d8c
Pointer value (address stored in ptr): 0x7ffee6f93d8c
Dereferenced pointer value: 10

In this example:

 &num gives the memory address of num.


 *ptr gives the value stored at the memory address that ptr is pointing to.

✅ Pointer to a Pointer (Double Pointer)

A pointer can also point to another pointer. This is called a pointer to a pointer, or double
pointer.

#include <stdio.h>

int main() {
int num = 5;
int *ptr = &num; // Pointer to num
int **ptr2 = &ptr; // Pointer to pointer (double pointer)

printf("Value of num: %d\n", num); // Output the value of num


printf("Value using *ptr: %d\n", *ptr); // Dereference ptr to get num
printf("Value using **ptr2: %d\n", **ptr2); // Dereference ptr2 to get num

96
return 0;
}
💻 Output:
Value of num: 5
Value using *ptr: 5
Value using **ptr2: 5

Here, ptr2 points to ptr, and ptr points to num. Using **ptr2 dereferences twice to access the
value of num.

✅ Pointer Arithmetic

Pointers support arithmetic operations like addition, subtraction, and comparison. This is
often used to navigate through arrays.

Example: Pointer Arithmetic with Arrays


#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Pointer to the first element of the array
// Accessing array elements using pointer arithmetic
printf("First element: %d\n", *ptr); // Dereferencing ptr to get the first element
printf("Second element: %d\n", *(ptr + 1)); // Moving pointer by 1 and dereferencing
printf("Third element: %d\n", *(ptr + 2)); // Moving pointer by 2 and dereferencing
return 0;
}
💻 Output:
First element: 10
Second element: 20
Third element: 30

In this example, ptr + 1 moves the pointer to the next memory location (which corresponds to
the next element in the array).

Call by Value vs Call by Reference in C

97
1. Call by Value

In call by value, a copy of the actual argument is passed to the function. Changes made to the
parameter inside the function do not affect the original argument.

 How it works: The function gets a copy of the value passed to it.
 Effect: The original variable remains unchanged outside the function.

Example of Call by Value:


#include <stdio.h>
void addTen(int num) {
num = num + 10; // This change will not affect the original argument
}
int main() {
int n = 5;
addTen(n); // Passes a copy of n
printf("Value of n after function: %d\n", n); // Output: 5 (original value unchanged)
return 0;
}
💻 Output:
Value of n after function: 5
2. Call by Reference

In call by reference, the address (reference) of the actual argument is passed to the function.
Changes made to the parameter inside the function affect the original argument.

 How it works: The function gets the memory address of the argument.
 Effect: The original variable is modified directly.

Example of Call by Reference:


#include <stdio.h>

void addTen(int *num) {


*num = *num + 10; // Dereference the pointer and modify the original value
}

98
int main() {
int n = 5;
addTen(&n); // Passes the address of n
printf("Value of n after function: %d\n", n); // Output: 15 (value modified)
return 0;
}
💻 Output:
Value of n after function: 15

Key Differences:

Aspect Call by Value Call by Reference

Parameter Passes a copy of the argument to the Passes the address of the argument
Passing function. (reference).

Effect on The original variable remains


The original variable is modified.
Original unchanged.

More memory used as a copy of the More efficient since no copy is made,
Memory Usage
argument is made. only a reference.

Pointers and Arrays in C

In C, pointers and arrays are closely related, as arrays can be accessed through pointers, and
pointers can be used to manipulate arrays efficiently.

Pointer to an Array

An array name is essentially a pointer to the first element of the array. You can use pointers
to access and manipulate array elements.

Example of Pointer and Array:


#include <stdio.h>
int main() {
int arr[] = {10, 20, 30};
int *ptr = arr; // Pointer to the first element of the array

99
// Accessing array elements using pointer
printf("First element: %d\n", *ptr); // Output: 10
printf("Second element: %d\n", *(ptr + 1)); // Output: 20
printf("Third element: %d\n", *(ptr + 2)); // Output: 30

return 0;
}
💻 Output:
First element: 10
Second element: 20
Third element: 30

ARRAYS OF POINTERS

Arrays of Pointers in C

An array of pointers is an array where each element is a pointer to a specific variable or data
type. This concept is commonly used when dealing with arrays of strings or when you need
to store the addresses of multiple variables in an array.

How It Works:

 Array of Pointers: The array itself stores memory addresses (pointers).


 Each Element: Each element of the array points to a specific value or data

✅ Example 1: Array of Pointers to Integers

#include <stdio.h>
int main() {
int a = 10, b = 20, c = 30;
// Array of pointers to integers
int *arr[] = {&a, &b, &c};
// Accessing elements through the pointers
printf("a: %d\n", *arr[0]); // Dereferencing pointer to access value
printf("b: %d\n", *arr[1]); // Dereferencing pointer to access value
printf("c: %d\n", *arr[2]); // Dereferencing pointer to access value

100
return 0;
}

💻 Output:
a: 10
b: 20
c: 30

 arr is an array of pointers, each pointing to the address of a, b, and c.


 The *arr[i] dereferences the pointer to access the value of the corresponding variable.

📚 Pointers and Structures in C

In C, pointers and structures are often used together to create flexible and dynamic
programs. Pointers to structures allow for dynamic memory management, efficient passing of
large structures to functions, and handling complex data types like linked lists.

Pointer to a Structure

A pointer to a structure is used to refer to a structure variable indirectly. The pointer holds
the address of the structure and can access its members using the -> operator.

Example: Pointer to a Structure


#include <stdio.h>
struct Person {
char name[50];
int age;
};
int main() {
struct Person person = {"Alice", 25};
struct Person *ptr = &person; // Pointer to the structure
// Accessing structure members using the pointer
printf("Name: %s\n", ptr->name); // Output: Alice
printf("Age: %d\n", ptr->age); // Output: 25
return 0;

101
}
💻 Output:
Name: Alice
Age: 25

In this example:

 ptr is a pointer to the structure person.


 ptr->name and ptr->age are used to access the structure members via the pointer.

2. Passing Structures to Functions Using Pointers

When you pass a structure to a function using a pointer, the function works with the actual
structure (not a copy), which is more efficient.

Example: Passing Structure to Function


#include <stdio.h>
struct Person {
char name[50];
int age;
};
// Function to modify the structure using a pointer
void updatePerson(struct Person *ptr) {
ptr->age = 30; // Update the age
}
int main() {
struct Person person = {"Bob", 25};
updatePerson(&person); // Passing address of person
printf("Updated Age: %d\n", [Link]); // Output: 30
return 0;
}
💻 Output:
Updated Age: 30

102
In this example:

 The function updatePerson() accepts a pointer to a struct Person.


 The age of the person is modified inside the function.

Key Points:

1. Pointer to Structure: A pointer can point to a structure and access its members using
the -> operator.
2. Efficient Function Passing: Passing structures by pointer avoids copying the entire
structure, which is more efficient.
3. Dynamic Memory Allocation: Pointers to structures are often used with functions
like malloc() to dynamically allocate memory for structures.

Static vs Dynamic Memory Allocation

In C, memory allocation refers to the process of reserving space in memory to store data.
There are two main types of memory allocation:

1. Static Memory Allocation

In static memory allocation, memory is allocated at compile time, before the program starts
running. The size and type of memory needed must be known in advance.

 Fixed Memory Size: The amount of memory is decided when the program is
compiled and cannot be changed during runtime.
 Automatic/Global Variables: Variables that are declared outside functions (global
variables) or with the static keyword (local static variables) are statically allocated.

Example of Static Memory Allocation:


#include <stdio.h>
int main() {
int arr[5]; // Array of size 5, memory allocated at compile time
// Initialize the array
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;

103
}
// Print the array
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
return 0;
}
💻 Output:0 10 20 30 40

 Here, arr[5] is statically allocated with memory for 5 integers at compile time.

Advantages of Static Memory Allocation:

 Faster access since memory is allocated at compile time.


 Simple to use and manage.

Disadvantages of Static Memory Allocation:

 Fixed size, cannot be changed at runtime.


 Can waste memory if the allocated size is larger than needed.

2. Dynamic Memory Allocation

In dynamic memory allocation, memory is allocated at runtime using functions like


malloc(), calloc(), realloc(), and free. This allows you to allocate memory as needed during
the program's execution, and the size can be adjusted dynamically.

 Flexible Memory Size: The size of the memory can be decided at runtime and can
change.
 Heap Memory: Dynamically allocated memory is taken from the heap, which is a
region of memory that is managed during program execution.

Example of Dynamic Memory Allocation:


#include <stdio.h>
#include <stdlib.h> // For malloc

104
int main() {
int *arr;
int n = 5;
// Dynamically allocate memory for 5 integers
arr = (int*)malloc(n * sizeof(int));
// Check if memory allocation is successful
if (arr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
// Initialize the array
for (int i = 0; i < n; i++) {
arr[i] = i * 10;
}
// Print the array
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
// Free the dynamically allocated memory
free(arr);
return 0;
}
💻 Output:0 10 20 30 40

 Here, memory for the array arr is dynamically allocated using malloc(), and the size is
determined at runtime.

Advantages of Dynamic Memory Allocation:

 Memory size can be adjusted during runtime based on the program's needs.
 Efficient use of memory since you can allocate just the required amount.

Disadvantages of Dynamic Memory Allocation:

 Slower than static allocation because memory allocation is done at runtime.

105
 Requires manual management (malloc to allocate, free to release) to avoid memory
leaks.

Summary of Differences:

Aspect Static Memory Allocation Dynamic Memory Allocation

Memory Allocation
At compile time. At runtime.
Time

Can be changed dynamically


Memory Size Fixed and known at compile time.
during execution.

Stack (for local variables) or Data


Type of Memory Heap (allocated from the heap).
segment (for globals).

Memory Automatically managed by the Requires manual management


Management compiler. using malloc(), free().

Speed Faster access. Slower due to runtime allocation.

More flexible (size can be


Flexibility Less flexible (fixed size).
changed).

Static Memory Allocation

 Definition: Memory is allocated at compile time before the program starts executing.
 Fixed Size: The size of the memory must be known in advance, and it cannot change
during runtime.
 Memory Allocation: Done automatically by the compiler for variables (e.g., arrays,
global/static variables).
 Types of Variables:
o Global Variables: Memory is allocated at compile time and stays for the
lifetime of the program.
o Local Variables: Memory is allocated for the function's duration.
o Static Variables: Retain their value across function calls.
 Access: Fast memory access since memory allocation is done at compile time.
 Example:int arr[5]; // Array of size 5, memory is allocated at compile time

106
Advantages:

 Simpler and faster to use.


 No need to worry about memory management.

Disadvantages:

 Memory size is fixed, cannot change during runtime.


 Can waste memory if the size is larger than needed.

Dynamic Memory Allocation

 Definition: Memory is allocated at runtime using functions like malloc(), calloc(),


realloc(), and free().
 Flexible Size: The size of memory can be determined during execution and can be
resized as needed.
 Memory Allocation: Done in the heap region of memory.
 Types of Functions:
o malloc(size): Allocates a block of memory of given size and returns a pointer
to it.
o calloc(n, size): Allocates memory for n elements, each of size size, and
initializes the memory to zero.
o realloc(ptr, size): Resizes a previously allocated memory block.
o free(ptr): Frees dynamically allocated memory.

 Memory Management: Requires manual allocation and deallocation (e.g., using


malloc and free).
 Example:

int *arr = (int*)malloc(5 * sizeof(int)); // Dynamically allocate memory for 5 integers


Advantages:

 Flexible memory size, can be adjusted at runtime.


 Efficient memory usage since you can allocate just the required memory.

107
Disadvantages:

 Slower than static allocation due to runtime operations.


 Requires manual memory management to avoid memory leaks (using free()).

Memory Management Functions in C:

1. malloc():
o Allocates a block of memory of the specified size.
o Returns a pointer to the allocated memory.
o Example:int *ptr = (int*)malloc(sizeof(int) * 10);

2. calloc():
o Allocates memory for an array of n elements, each of a specified size, and
initializes all bytes to 0.
o Example:int *arr = (int*)calloc(5, sizeof(int));

3. realloc():
o Resizes previously allocated memory to a new size.
o Example:arr = (int*)realloc(arr, 10 * sizeof(int)); // Resize to store 10
elements

4. free():
o Deallocates previously allocated memory, releasing it back to the system.
o Example:free(arr);

Key Differences:

Aspect Static Memory Allocation Dynamic Memory Allocation

Memory Allocation At runtime using functions like


At compile time.
Time malloc.

Fixed size, defined at compile Size can be determined and


Memory Size
time. changed during execution.

Memory Region Stack (for local variables) or Data Heap (dynamically allocated

108
Aspect Static Memory Allocation Dynamic Memory Allocation

segment (globals). memory).

Memory Requires manual management


Automatically managed.
Management (malloc, free).

Faster due to compile-time


Speed Slower due to runtime allocation.
allocation.

Less flexible, cannot change size More flexible, size can be changed
Flexibility
after allocation. during runtime.

Example Comparison:

Static Memory Allocation:


int arr[5]; // Static array of size 5, allocated at compile time
Dynamic Memory Allocation:
int *arr = (int*)malloc(5 * sizeof(int)); // Dynamically allocate memory for 5 integers

Files in C: Definition

In C, a file is a collection of data stored in a specific format, usually on a storage device (like
a hard drive). Files are used to read, write, and store data for later use. C provides built-in
functions to work with files, allowing you to interact with external data easily.

1. File Operations in C

There are four basic operations you can perform on a file in C:

 Opening a file (fopen()).


 Reading from a file (fgetc(), fgets(), fread()).
 Writing to a file (fputc(), fputs(), fwrite()).
 Closing a file (fclose())

109
2. File Types

Files in C are classified into two types:

1. Text Files: Files that contain data in readable text format. Each line ends with a
newline character.
2. Binary Files: Files that store data in binary format, typically used for storing data
other than text (e.g., images, audio).

3. File Handling Functions

1. fopen():
o Opens a file for reading or writing.
o Syntax: FILE *fopen(const char *filename, const char *mode);
o Modes:
 "r": Read (file must exist).
 "w": Write (creates a new file or truncates an existing file).
 "a": Append (writes data at the end of the file).
 "rb", "wb", etc.: Binary mode.

Example:FILE *file = fopen("[Link]", "r");

2. fclose():
o Closes the file after the operation is completed.
o Syntax: int fclose(FILE *file);
o Always close files after operations to avoid memory leaks.

Example:fclose(file);

3. fgetc():
o Reads a single character from the file.
o Syntax: int fgetc(FILE *file);
o Returns the character read or EOF on error.

Example:char c = fgetc(file);
110
4. fgets():
o Reads a string from the file.
o Syntax: char *fgets(char *str, int n, FILE *file);
o Reads up to n-1 characters or until a newline is encountered.

Example:char buffer[100];

fgets(buffer, 100, file);

5. fputc():
o Writes a single character to the file.
o Syntax: int fputc(int c, FILE *file);

Example:fputc('A', file); // Write 'A' to the file

6. fputs():
o Writes a string to the file.
o Syntax: int fputs(const char *str, FILE *file);

Example:fputs("Hello, World!", file);

7. fread():
o Reads a block of data from the file.
o Syntax: size_t fread(void *ptr, size_t size, size_t count, FILE *file);

Example:char buffer[50];

fread(buffer, sizeof(char), 50, file);

8. fwrite():
o Writes a block of data to the file.
o Syntax: size_t fwrite(const void *ptr, size_t size, size_t count, FILE *file);

111
Example:fwrite(buffer, sizeof(char), 50, file);

4. File Modes

When opening a file, you specify the mode which defines how you want to interact with the
file:

 "r": Read (file must exist).


 "w": Write (creates new or overwrites existing file).
 "a": Append (adds data at the end).
 "rb": Read binary.
 "wb": Write binary.
 "a+": Append and read.
 "r+": Read and write (file must exist).
 "w+": Write and read (creates a new file or truncates).

5. Error Handling

File operations may fail, so it's essential to check for errors:

 Check if a file is opened successfully:

if (file == NULL) {
printf("Error opening file!\n");
}

 Check for end-of-file (EOF):

if (feof(file)) {
printf("End of file reached.\n");
}

6. Example: Reading and Writing to a File

#include <stdio.h>

112
int main() {
FILE *file;
char content[100];

// Open the file for writing


file = fopen("[Link]", "w");
if (file == NULL) {
printf("Error opening file.\n");
return 1;
}
// Write to the file
fputs("Hello, World!\n", file);
fclose(file); // Close the file after writing
// Open the file for reading
file = fopen("[Link]", "r");
if (file == NULL) {
printf("Error opening file.\n");
return 1;
}
// Read from the file
fgets(content, 100, file);
printf("File content: %s", content);
fclose(file); // Close the file after reading
return 0;
}
💻 Output:File content: Hello, World!

Text and Binary Files in C:

In C, files are primarily classified into text files and binary files. These two types of files
differ in how data is stored and processed.

1. Text Files

113
 Definition: Text files store data in a human-readable format. Each line of text is
typically terminated with a newline (\n) character.
 Data Representation: Data is stored as a sequence of characters (ASCII or Unicode),
making it easy to read and edit using text editors.
 File Operations: You can open text files with modes like "r", "w", "a", and "r+".

Example of Text File Content:


Hello, World!
This is a text file.
Common Functions:

 fgets(): Reads a line from a text file.


 fputs(): Writes a string to a text file.

2. Binary Files

 Definition: Binary files store data in its raw binary format (i.e., 0s and 1s), typically
used for non-text data like images, audio, and executable programs.
 Data Representation: Data is stored as bytes (8 bits) rather than characters. The
structure of the data is more complex and specific to the application.
 File Operations: You can open binary files with modes like "rb", "wb", and "r+".

Example of Binary File Content:

A binary file could contain bytes representing an image or a serialized data structure (not
human-readable).

Common Functions:

 fread(): Reads data from a binary file.


 fwrite(): Writes data to a binary file.

Key Characteristics:

 Not Readable: Cannot be opened and edited in a text editor, as it's not meant to be
human-readable.
 Byte-Based: Stores data as raw bytes, which could represent any type of data.

114
 No Line Terminators: Unlike text files, binary files do not have specific line-ending
characters.

Key Differences:

Aspect Text Files Binary Files

Data
Human-readable characters (ASCII). Raw binary data (0s and 1s).
Representation

Can be processed with functions like Can be processed with functions


File Operations
fgetc(), fputs(). like fread(), fwrite().

Easily portable across systems (if System-dependent due to byte-


Portability
newline format matches). ordering.

Typically smaller because it's raw


Size Larger due to text encoding.
data.

Cannot be easily edited in text


Editability Can be edited in a text editor.
editors.

Line Terminators Newline characters (\n or \r\n). No specific line terminators.

When to Use Text Files vs Binary Files?

 Use text files when:


o You need human-readable content.
o The data consists primarily of characters or text (e.g., logs, configuration
files).
 Use binary files when:
o You need to store complex data types like images, audio, or structures.
o The data should not be easily editable or readable by humans.

115
Command-Line Arguments in C:

In C, command-line arguments allow you to pass data to your program when it is executed
from the terminal or command prompt. These arguments can be used to provide input values,
configurations, or other parameters to influence the behavior of the program.

1. Definition

Command-line arguments are inputs provided after the program's name in the
terminal/command prompt when running a C program. They are passed to the main()
function as parameters.

 Syntax:

int main(int argc, char *argv[])

o argc: Argument Count - The number of arguments passed, including the


program name.

 argv: Argument Vector - An array of strings (character pointers) that stores


 each argument passed to the program.

2. Understanding argc and argv

 argc (Argument Count):


o Represents the total number of arguments passed to the program, including the
program name.
o It is always at least 1 (because the program's name is always passed as the first
argument).

 argv (Argument Vector):


o An array of strings (char*), where each element represents one command-line
argument.
o argv[0] is always the name of the program.
o argv[1], argv[2], etc., are the arguments passed by the user.

116
3. Example Usage

Example: Program using Command-Line Arguments


#include <stdio.h>
int main(int argc, char *argv[]) {
// Check if enough arguments are passed
if (argc != 3) {
printf("Usage: %s <arg1> <arg2>\n", argv[0]);
return 1;
}
// Print the arguments
printf("Program Name: %s\n", argv[0]);
printf("First Argument: %s\n", argv[1]);
printf("Second Argument: %s\n", argv[2]);
return 0;
}
Output:
Program Name: ./program
First Argument: Hello
Second Argument: World

4. Important Points

 Argument Count (argc):


o The value of argc tells you how many arguments were passed to the program.
o The first argument (argv[0]) is always the program's name.

 Argument Vector (argv):


o The array argv[] holds the arguments passed.
o Each argument is stored as a string (char array).

 Error Handling:
o Always check argc to make sure the correct number of arguments is passed.
o Handle errors if insufficient arguments are provided.

117
5. Example with Integer Argument Parsing

To convert command-line arguments into integers, use atoi() (or strtol() for more control).

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {


if (argc != 3) {
printf("Usage: %s <num1> <num2>\n", argv[0]);
return 1;
}
// Convert arguments to integers
int num1 = atoi(argv[1]);
int num2 = atoi(argv[2]);
printf("Sum: %d\n", num1 + num2);
return 0;
}
Example:
Output:Sum: 15

6. Summary of Command-Line Arguments

 Syntax:
int main(int argc, char *argv[])
o argc: Total count of arguments (including program name).
o argv[]: Array of strings holding each argument passed.

 Common Usage:
o Configuring program behavior.
o Passing user input to a program without interactive prompts.

 Error Handling:
o Check argc to ensure the required number of arguments.
o Use atoi() or strtol() to convert strings to integers.

118
Preprocessor Directives in C: Short Notes

Preprocessor directives in C are commands that are processed by the preprocessor before the
actual compilation of the program begins. They are used to include files, define constants,
and conditionally compile parts of the code.

1. Definition

Preprocessor directives are lines in the program that start with a # symbol. They provide
instructions to the preprocessor which modifies the code before it is compiled.

2. Common Preprocessor Directives

1. #include

 Purpose: Includes the contents of a file (usually a header file) in the program.
 Usage:
o #include <file>: Includes system/library header files.
o #include "file": Includes user-defined header files.

Example:

#include <stdio.h> // Includes standard input/output functions


#include "myfile.h" // Includes user-defined header file

2. #define

 Purpose: Defines a constant or macro.


 Usage: Used to define symbolic constants or macros that can be replaced in the code
before compilation.

Syntax:

#define CONSTANT_NAME value

Example:

119
#define PI 3.14159 // Defines a constant PI
#define SQUARE(x) ((x) * (x)) // Defines a macro for squaring a number

3. #undef

 Purpose: Undefines a previously defined macro.


 Usage: Removes the definition of a macro that was set with #define.

Example:

#define MAX 100


#undef MAX // Undefines the MAX constant

4. #if, #else, #elif, #endif

 Purpose: Conditional compilation—compiles certain code blocks depending on


whether a condition is true.

Syntax:

#if CONDITION
// Code if condition is true
#elif ANOTHER_CONDITION
// Code if the second condition is true
#else
// Code if none of the conditions are true

#endif

Example:

#define DEBUG

#if defined(DEBUG)

120
printf("Debugging is enabled.\n");
#else
printf("Debugging is disabled.\n");
#endif
5. #ifdef and #ifndef

 Purpose: Conditional compilation based on whether a macro is defined or not.


 #ifdef checks if a macro is defined.
 #ifndef checks if a macro is not defined.

Example:

#define PI 3.14
#ifdef PI
printf("PI is defined.\n");
#endif
#ifndef MAX_SIZE
printf("MAX_SIZE is not defined.\n");
#endif
6. #pragma

 Purpose: Provides special instructions to the compiler (compiler-specific).


 Usage: Used to control specific compiler behavior, such as optimization or warnings.

Example:#pragma once // Ensures the header file is included only once

3. Why Use Preprocessor Directives?

 Modular Code: Use #include to include header files and split the code into multiple
files.
 Constants and Macros: Use #define to define constants and macros for reusable
code.
 Conditional Compilation: Use #if, #ifdef, etc., to include/exclude parts of code
depending on the conditions, such as debugging or platform-specific code.

4. Example Using Multiple Directives

121
#include <stdio.h>
#define MAX 100
int main() {
int arr[MAX];
#ifdef MAX
printf("MAX is defined as %d\n", MAX);
#endif
#if MAX > 50
printf("MAX is greater than 50\n");
#else
printf("MAX is less than or equal to 50\n");
#endif
return 0;
}
Output:
MAX is defined as 100
MAX is greater than 50

5. Summary of Common Directives

Directive Purpose Example

#include Includes a header file or library #include <stdio.h>

#define Defines a constant or macro #define PI 3.14

#undef Undefines a previously defined macro #undef PI

#if Conditional compilation (if condition is true) #if DEBUG

#ifdef Conditional compilation if a macro is defined #ifdef DEBUG

#ifndef Conditional compilation if a macro is not defined #ifndef DEBUG

#else Alternative branch in conditional compilation #else

#elif Else if condition in conditional compilation #elif CONDITION

#endif Ends a conditional block #endif

122
Directive Purpose Example

Provides special instructions to the compiler (compiler-


#pragma #pragma once
specific)

Macros in C: Definition and Types

In C, macros are a type of preprocessor directive that allows you to define reusable code or
values. Macros are processed by the preprocessor before the actual compilation starts, making
them powerful tools for simplifying complex code, enhancing readability, and improving
maintainability.

1. Definition of Macros

A macro is a name that represents a code fragment. When the preprocessor encounters the
macro name in the code, it replaces it with the defined code.

Syntax:

#define MACRO_NAME replacement_text

 Example:

#define PI 3.14159 // Defines a constant macro

2. Types of Macros

There are two main types of macros in C:

123
1. Object-like Macros

 Definition: Object-like macros represent constants or expressions. They are simple


replacements for values or code blocks.
 Usage: Typically used for defining constants or simple values.

Syntax:

#define MACRO_NAME value

Example:

#define MAX_SIZE 100


#define PI 3.14159

 Usage: The preprocessor replaces MAX_SIZE with 100 and PI with 3.14159
wherever they appear in the code.

Example in Code:

#include <stdio.h>
#define MAX_SIZE 100

int main() {
int arr[MAX_SIZE];
printf("Array size: %d\n", MAX_SIZE);
return 0;
}
2. Function-like Macros

 Definition: Function-like macros represent a function and are defined with


parameters. The preprocessor replaces the macro with the corresponding code,
including the passed arguments.
 Usage: Used for short, inline code that operates on arguments, similar to a function.

Syntax:

124
#define MACRO_NAME(arg1, arg2, ...)
replacement_expression

Example:

#define SQUARE(x) ((x) * (x))

 Usage: The preprocessor replaces SQUARE(5) with ((5) * (5)).

Example in Code:

#include <stdio.h>
#define SQUARE(x) ((x) * (x))

int main() {
int result = SQUARE(5);
printf("Square of 5: %d\n", result); // Output: Square of 5: 25
return 0;
}

3. Advantages of Macros

 Efficiency: Macros are processed at compile time, making them faster than functions.
 Code Reusability: Macros allow you to reuse code with minimal redundancy.
 Flexibility: They can be used for constants, expressions, and even code snippets.
 Conditionally include code: Macros can be used to include or exclude code based on
conditions (e.g., using #ifdef).

4. Disadvantages of Macros

 No Type Checking: Macros are simple text replacements, so there is no type


checking. This can lead to bugs if the arguments are not used properly.

Example:

#define SQUARE(x) ((x) * (x))

125
printf("%d\n", SQUARE(2 + 3)); // Expands to ((2 + 3) * (2 + 3)) => 5 * 5 = 25

 Debugging Difficulty: Since macros are expanded at compile time, debugging can be
tricky.

5. Advanced Macro Features

1. Macro with Multiple Arguments

You can define macros that take multiple arguments:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

Example Usage:

int larger = MAX(10, 20); // Returns 20


2. Stringizing Operator (#)

The stringizing operator converts macro arguments into a string:

#define TO_STRING(x) #x

Example Usage:

printf("%s\n", TO_STRING(Hello)); // Output: "Hello"


3. Concatenation Operator (##)

The concatenation operator concatenates two tokens together:

#define CONCAT(a, b) a##b

Example Usage:

int xy = 10;
printf("%d\n", CONCAT(x, y)); // Output: 10

6. Summary of Macro Types

126
Type Description Example

Object-like Macro Simple replacement of values or constants. #define PI 3.14159

Function-like Macro that behaves like a function with #define SQUARE(x) ((x) *
Macro arguments. (x))

Creating and Implementing User-Defined Header Files in C

In C, header files are used to declare function prototypes, constants, and types, which can be
shared between multiple source files. You can create your own header files to organize code
and improve reusability.

1. What is a Header File?

A header file is a file that contains definitions or declarations that are shared across multiple
source files. It usually has a .h extension and is included at the top of C source files using the
#include directive.

 Example of a header file: myheader.h

2. Steps to Create and Implement a User-Defined Header File

1. Create the Header File

Create a .h file that contains function prototypes, constants, and type definitions. This file
doesn't contain function definitions or logic; it only contains declarations.

Example: myheader.h

127
#ifndef MYHEADER_H // Include guard to prevent double inclusion
#define MYHEADER_H

#define PI 3.14159 // Constant definition


#define SQUARE(x) ((x) * (x)) // Macro definition

void printMessage(); // Function prototype

#endif

 #ifndef MYHEADER_H: Checks if the MYHEADER_H macro is already defined.


 #define MYHEADER_H: Defines the macro to prevent multiple inclusions of the
same file.
 #endif: Ends the preprocessor block.

2. Create the Source File

In the source file (.c), include the header file using #include to access the declarations.

Example

#include <stdio.h>
#include "myheader.h" // Including the user-defined header file

void printMessage() {
printf("Hello from the header file!\n");
}
int main() {
printf("Value of PI: %f\n", PI);
printf("Square of 5: %d\n", SQUARE(5));
printMessage();
return 0;
}

128
 #include "myheader.h": Includes the header file in your source file, making its
contents available for use.
 Function printMessage() is defined in main.c, while its prototype is declared in the
header file.

3. Compilation Process

 The header file (myheader.h) is included in the source file (main.c).


 When the program is compiled, the preprocessor replaces #include "myheader.h" with
the actual contents of the header file.
 The header file can be included in multiple source files, allowing code reusability.

4. Benefits of Using Header Files

 Code Reusability: Declare functions, constants, and structures in the header file, and
reuse them across different .c files.
 Modularity: Separate function declarations and definitions, making code easier to
maintain.
 Encapsulation: Hide implementation details and expose only the necessary functions
through the header file.
 Avoid Redundancy: Use #ifndef and #define to avoid multiple inclusions of the same
header file.

5. Example Project Structure

project/

├── myheader.h // User-defined header file
├── main.c // Source file using the header file
└── Makefile // Makefile for compiling the program (optional)

129
130

You might also like