C Programming Notes
C Programming Notes
When writing programs in any programming language, including C, errors can occur that prevent the
program from functioning correctly. In C programming, errors are broadly categorized into three types:
syntax errors, semantic errors, and runtime errors.
I. Syntax Errors:
Syntax errors occur when the code violates the rules of the programming language. Syntax errors are
detected and caught by the compiler during the compilation process. These errors prevent the program
from being compiled or executed. Common causes of syntax errors include missing semicolons,
mismatched parentheses, misspelled keywords, and incorrect use of operators.
Semantic errors occur when the code is grammatically correct but does not behave as intended. In other
words, the program compiles and executes without any error messages, but the output or behavior is
not as expected. Semantic errors are logical mistakes in the program's design or implementation. They
can lead to incorrect program behavior, calculation errors, or unexpected results. These errors are
harder to detect because the compiler cannot identify them.
Examples of semantic errors include using the wrong formula, improper handling of data types, or
incorrect algorithm implementation.
Runtime errors occur when the program is running and encounters an unexpected condition that
prevents it from executing further. These errors are typically caused by issues such as division by zero,
accessing invalid memory, or incorrect input values. Runtime errors are detected during program
execution. They often cause the program to terminate abruptly or produce incorrect results.
1. Simple Syntax: C has a simple and straightforward syntax, making it easier to learn and understand for
beginners. The language uses a small set of keywords and a clear structure, making it readable and
concise.
2. Efficiency: C is known for its efficiency in terms of execution speed and memory usage. It allows direct
access to memory addresses, low-level operations, and efficient control over hardware.
3. Portability: C programs are highly portable, meaning they can be compiled and run on different
platforms with minimal modifications. This portability is achieved through the availability of compilers
for various hardware and operating systems.
4. Extensibility: C supports the use of external libraries and function modules, allowing programmers to
extend the language's functionality. This feature enables code reuse, faster development, and the ability
to incorporate existing code libraries into new projects.
5. Modularity: C allows the creation of modular programs by dividing them into separate functions or
modules. This modular approach promotes code organization, reusability, and easier maintenance.
2. Advantages of C:
1. Speed: C is a compiled language, which means it is translated into machine code before execution.
This compilation process results in faster execution speed compared to interpreted languages, making it
suitable for performance-critical applications.
2. Low-Level Manipulation: C provides direct access to memory addresses and low-level operations,
allowing programmers to write efficient code for system-level tasks like operating systems, drivers, and
embedded systems.
3. Wide Range of Applications: versatility and efficiency make it a popular choice for software
development in areas like system programming, game development, embedded systems etc.
3. Disadvantages of C:
1. Complexity: Although C has a simple syntax, it can be complex for beginners due to its low-level
features, pointers, and memory management.
2. Lack of Built-in Support: C does not provide built-in support for advanced data structures like dynamic
arrays, strings, and objects.
3. Memory Management: C does not have automatic memory management mechanisms like garbage
collection. Programmers are responsible for managing memory allocation and deallocation, which can
lead to memory leaks and segmentation faults if not handled correctly.
4. Absence of Standard Libraries: C does not include comprehensive standard libraries for tasks like
string manipulation, input/output, and data structures. Programmers often have to rely on external
libraries or write custom code to fulfill these requirements.
1. Structure of a C Program:
A C program is composed of various elements. The structure of a C program generally consists of the
following components:
a. Preprocessor Directives:
Preprocessor directives are statements that guide the preprocessor, a program that processes the
source code before compilation. These directives begin with a hash symbol (#) and include header files
and macros. Common preprocessor directives include #include, #define.
b. Global Declarations:
Global declarations are used to define variables and functions that are accessible throughout the
program. These declarations are placed outside any function, typically at the beginning of the program.
c. Function Declarations:
Function declarations or prototypes provide information about the functions used in the program. They
specify the function name, return type, and the types of arguments (if any). Function declarations are
generally placed before the main() function.
d. Main Function:
The main() function is the starting point of execution in a C program. It is mandatory and must be
defined. The main() function contains the program's logic and controls the flow of execution.
e. User-defined Functions:
Apart from the main() function, a C program can have user-defined functions. These functions are
written to perform specific tasks and can be called from the main() function or other functions.
a. Preprocessing:
In this stage, the preprocessor examines the source code and performs tasks defined by preprocessor
directives. These tasks include inserting the content of header files (#include), and/or including any
additional header files library like Math required during the code execution.
b. Compilation:
The compiler translates the preprocessed code into assembly language or machine code. It checks the
syntax and semantics of the code, detects errors, and generates object code files. Any errors or warnings
are reported at this stage.
c. Linking:
If the program consists of multiple source code files or uses external libraries, the linking stage comes
into play. The linker combines the object code files with any required libraries to create an executable
file. It resolves references to functions and variables defined in different files.
d. Execution:
The final output of the compiling process is an executable file. This file contains machine instructions
that can be executed by the computer's processor. When the program is run, the operating system loads
the executable file into memory and starts executing it.
Character Set, Data Types, Variables, Tokens, Header Files, and Library Functions
ASCII (American Standard Code for Information Interchange) consists of 128 characters, including
letters, digits, symbols, and control characters.
Example:
Data Types:
Data types define the type of data that can be stored in a variable.
char: used to store individual characters (e.g., 'A', 'b', '1'). => %c
double: used to store double-precision floating-point numbers. (e.g., 3.14159265359, 123.456) => lf
short: used to store smaller integers. (e.g., -10, 500 )=> %hd
Example:
Variables:
Variables are named memory locations used to store data during program execution.
Variable names can consist of letters, digits, and underscore (_), but must start with a letter or
underscore.
Variable names are case-sensitive (e.g., age and Age are different).
Avoid using reserved keywords as variable names (e.g., int, float, etc.).
Syntax for variable declaration and assignment: data_type variable_name = value;
Example:
C Tokens:
Types of tokens:
Example:
if (condition) {
// code block
} else {
// code block
Identifiers:
Identifiers are user-defined names used to represent variables, functions, arrays, and other entities in a
C program. Identifiers can consist of letters (both lowercase and uppercase), digits, and underscore
(_).The first character of an identifier must be a letter or an underscore. It cannot start with a digit.
Identifiers are case-sensitive, meaning that age and Age are considered as different identifiers. Avoid
using reserved keywords (e.g., int, float, if, etc.) as identifiers, as they have predefined meanings in the C
language.
Example:
Example:
Example:
int sum = a + b; // Addition operator
Header Files:
Header files contain predefined functions and macros that can be used in a C program.
Example:
#include <stdio.h>
int main() {
printf("Hello, world!");
return 0;
Library Functions:
Library functions are functions provided by C libraries that perform specific tasks.
They are declared in the corresponding header files and defined in library files.
Example:
#include <stdio.h>
#include <math.h>
int main() {
return 0;
Preprocessor directives are instructions to the preprocessor, which is a part of the C compiler. These
directives are processed before the actual compilation of the code begins. They are used to include
header files, define macros, and perform conditional compilation.
Syntax:
#include <header_file.h>
Example:
#ifdef DEBUG_MODE
#else
#endif
int main() {
return 0;
2. Escape Sequences:
Escape sequences are special characters that are used to represent non-printable characters or provide
additional functionalities. They are denoted by a backslash () followed by a character or a combination
of characters.
Syntax:
\character
Example:
#include <stdio.h>
int main() {
return 0;
3. Comments:
Comments are used to add explanatory text within the source code. They are ignored by the compiler
and have no impact on the program's execution. Comments help in improving code readability and
understanding.
Syntax:
// Single-line comment
/*
Multi-line
comment
*/
Example:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
/*
This is a
multi-line comment
*/
return 0;
Formatted input/output functions are used to perform input and output operations with formatted
data. They allow you to control the format of data being displayed or read. The two commonly used
formatted input/output functions in C are printf() and scanf().
1.1 printf() Function:
The printf() function is used to print formatted output to the console or other output devices. It takes a
format string as the first argument, which specifies the layout and format of the output, followed by the
values to be displayed.
Example:
#include <stdio.h>
int main() {
return 0;
Output:
The scanf() function is used to read formatted input from the user or input devices. It takes a format
string as the first argument, which specifies the expected format of the input, followed by the memory
addresses where the values should be stored.
Example:
#include <stdio.h>
int main() {
int age;
float height;
scanf("%d", &age);
scanf("%f", &height);
return 0;
Output:
Enter your age: 25
The getchar() function reads a single character from the input, while the putchar() function prints a
single character to the output.
Syntax:
int getchar(void);
Example:
#include <stdio.h>
int main() {
int c;
c = getchar();
putchar(c);
return 0;
Output:
Enter a character: A
You entered: A
The gets() function reads a line of text from the input until a newline character is encountered. It stores
the input in the provided character array. The puts() function prints a string to the output followed by a
newline character.
Syntax:
char *gets(char *str);
Example:
#include <stdio.h>
int main() {
char name[50];
gets(name);
printf("Hello, ");
puts(name);
return 0;
Output:
The getc() function reads a single character from the input, similar to getchar(). The putc() function
writes a single character to the output, similar to putchar().
Syntax:
Example:
#include <stdio.h>
int main() {
FILE *file;
char c;
if (file) {
c = getc(file);
putc(c, stdout);
fclose(file);
return 0;
Output:
Operators:
Operators are symbols or special characters that perform specific operations on one or more operands.
C programming language provides various types of operators, such as arithmetic, relational, logical,
assignment, bitwise, etc.
1. Arithmetic Operators:
#include <stdio.h>
int main() {
int a = 10;
int b = 3;
int result;
result = a + b; // Addition
result = a - b; // Subtraction
result = a * b; // Multiplication
result = a / b; // Division
return 0;
2. Relational Operators:
Relational operators compare the values of two operands and return a Boolean result (1 for true, 0 for
false).
Examples: == (equal to), != (not equal to), > (greater than), < (less than), >= (greater than or equal to), <=
(less than or equal to).
#include <stdio.h>
int main() {
int a = 10;
int b = 3;
int result;
result = a == b; // Equal to
return 0;
3. Logical Operators:
Logical operators are used to perform logical operations on Boolean expressions or conditions.
Logical operators are used to perform logical operations on Boolean values (0 or 1) or expressions. They
evaluate the truth value of conditions and help in making decisions based on the outcome. In C
programming, the following logical operators are available:
The logical AND operator returns true (1) if both operands are true, otherwise, it returns false (0). It can
be represented as "&&" in C. The syntax is as follows:
Example:
int a = 5, b = 10, c = 3;
} else {
Logical OR (||):
The logical OR operator returns true (1) if at least one of the operands is true. If both operands are false,
it returns false (0). It can be represented as "||" in C. The syntax is as follows:
Example:
} else {
The logical NOT operator reverses the truth value of the operand. If the operand is true, it returns false
(0), and if the operand is false, it returns true (1). It can be represented as "!" in C. The syntax is as
follows:
Syntax
result = !operand;
Example:
int isRaining = 0;
if (!isRaining) {
printf("You can go outside.");
} else {
printf("Stay indoors.");
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int c = 15;
int result;
return 0;
4. Assignment Operators:
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
a += b; // a = a + b
a -= b; // a = a - b
a /= b; // a = a / b
a %= b; // a = a % b
return 0;
5. Bitwise Operators:
Bitwise operators perform operations at the bit level of operands. Bitwise operators are used to
manipulate individual bits in binary representations of data. These operators perform operations at the
bit level, which can be useful in various scenarios such as setting or clearing specific bits, checking for
the presence of certain flags, or performing bitwise calculations. Bitwise operators are commonly used
in low-level programming, such as manipulating hardware registers or working with binary data.
It's important to be cautious when using bitwise operators because they can easily introduce
unexpected results if used incorrectly.
The bitwise AND operator compares the corresponding bits of two operands and produces a result with
bits set only where both operands have corresponding bits set.
Syntax:
Example:
The bitwise OR operator compares the corresponding bits of two operands and produces a result with
bits set where either or both operands have corresponding bits set.
Syntax:
Example:
The bitwise XOR operator compares the corresponding bits of two operands and produces a result with
bits set where only one of the operands has the corresponding bit set.
Syntax:
result = operand1 ^ operand2;
Example:
int result = a ^ b;
The bitwise NOT operator flips the bits of the operand. It converts each 0 bit to 1 and each 1 bit to 0.
Syntax:
result = ~operand;
Example:
The left shift operator shifts the bits of the left operand to the left by a specified number of positions. It
effectively multiplies the left operand by 2 raised to the power of the right operand.
Syntax:
Example:
The right shift operator shifts the bits of the left operand to the right by a specified number of positions.
It effectively divides the left operand by 2 raised to the power of the right operand.
Syntax:
Example:
Examples: & (bitwise AND), | (bitwise OR), ^ (bitwise XOR), << (left shift), >> (right shift).
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int result;
result = a | b; // Bitwise OR
return 0;
6. Operand:
int main() {
int a = 5;
int b = 3;
int result;
return 0;
7. Operation:
8. Expression:
An expression is a combination of operands, operators, and parentheses (if required) that results in a
value.
#include <stdio.h>
int main() {
int a = 5;
int b = 10;
int c = 15;
int result;
result = (a * b) + c; // Expression: (a * b) + c
return 0;
2. Binary Operators:
Examples:
3. Ternary Operator:
The ternary operator works with three operands and acts as a short form of the if-else statement.
Example:
Conditional Operator (?): Evaluates a condition and returns a value based on the result.
4. Arithmetic Operators:
Examples:
Addition (+)
Subtraction (-)
Multiplication (*)
Division (/)
Modulus (%)
5. Relational Operators:
Relational operators compare two values and return a Boolean result (true or false).
Examples:
Equal to (==)
6. Logical Operators:
Examples:
Logical OR (||)
7. Assignment Operators:
Examples:
Assignment (=)
8. Increment/Decrement Operators:
Increment and decrement operators increase or decrease the value of a variable by one.
Examples:
9. Conditional Operator:
Example:
Examples:
Bitwise OR (|)
Example:
Operators Precedence:
Operator precedence determines the order in which operators are evaluated in an expression.
Operators with higher precedence are evaluated before those with lower precedence.
#include <stdio.h>
int main() {
int result = 2 + 3 * 4; // Multiplication has higher precedence
return 0;
Operators Associativity:
Operator associativity determines the order in which operators of the same precedence in an expression
are evaluated.
Example for associativity:
#include <stdio.h>
int main() {
return 0;
1. Left-to-right associativity:
Operators with left-to-right associativity are evaluated from left to right.
Example: a + b + c is evaluated as ((a + b) + c)
2. Right-to-left associativity:
Operators with right-to-left associativity are evaluated from right to left.
Example: a = b = c is evaluated as (a = (b = c))
Higher precedence level means that the operator is evaluated before those with a lower precedence
level. Operators at the same level have their associativity determined by the "Associativity" column.
Implicit type conversion, also known as "coercion," happens automatically by the compiler when the
data types in an expression are compatible. It ensures that the operands are of the same type before
performing the operation. Implicit conversions occur when a value of one data type is assigned to a
variable of another data type that can represent a wider range of values without loss of precision.
The hierarchy of implicit conversions is as follows:
Example:
float result;
In the example above, the integer num1 is implicitly converted to a float before adding it to num2. The
result is stored in the float variable result.
Type casting is a manual conversion of one data type to another, overriding the implicit type conversion.
It allows us to explicitly specify the desired data type for an expression. Type casting allows us to
override the default implicit conversion behavior. Explicit conversions are also known as forced
conversions or narrowing conversions
Syntax:
(type) expression
Example:
int num2 = 3;
float result;
In the above example, the integer num1 is explicitly cast to a float before performing the division
operation with num2. The result is stored in the float variable result.
Sequential Statements:
Sequential statements consist of individual instructions or expressions that are executed one after
another in the order they appear. The syntax for sequential statements is straightforward:
Syntax:
instruction1;
instruction2;
instruction3;
// Additional instructions...
Example:
int x = 5;
printf("The value of x is %d\n", x);
x = x + 3;
printf("After adding 3, the value of x is %d\n", x);
Output:
The value of x is 5
After adding 3, the value of x is 8
1. If statements:
The if statement allows execution of a block of code if a specified condition is true. The if statement first
evaluates the expressions and then it executes the statement within its block if the value of evaluation
expression is true.
Syntax:
if (condition)
{
// Code to be executed if the condition is true
}
Example:
#include <stdio.h>
int main()
{
int age;
printf("Enter your age: ");
scanf("%d", &age);
if (age >= 18)
{
printf("You are eligible to vote.\n");
}
printf("Program execution continues.\n");
return 0;
}
2. If…else statements:
The if-else statement extends the functionality of the if statement by allowing you to execute a different
block of code when the condition is false. If the condition in the if statement evaluates to false, the block
of code inside the else statement is executed. It is used when there are two possible options, one
happening when option is true, other when option is false.
Syntax:
if (condition)
{
// Code to be executed if the condition is true
}
else
{
// Code to be executed if the condition is false
}
Example:
#include <stdio.h>
int main()
{
int num;
printf("Enter a number: ");
scanf("%d", &num);
if (num % 2 == 0)
{
printf("The number is even.\n");
}
else
{
printf("The number is odd.\n");
}
return 0;
}
3. If…else…if…else statements:
The if-else if-else statement allows to test multiple conditions one after another and execute the
corresponding block of code that matches the first true condition. It provides a way to handle multiple
scenarios in a more structured manner.
Syntax:
if (condition1)
{
// Code to be executed if condition1 is true
}
else if (condition2)
{
// Code to be executed if condition2 is true
}
...
else
{
// Code to be executed if none of the above conditions are true
}
Example:
#include <stdio.h>
int main()
{
int score;
printf("Enter your score: ");
scanf("%d", &score);
if (score >= 90)
{
printf("Grade A\n");
}
else if (score >= 80)
{
printf("Grade B\n");
}
else if (score >= 70)
{
printf("Grade C\n");
}
else
{
printf("Grade D\n");
}
return 0;
}
Nested if-else statements involve placing if statements inside other if or else statements. This allows for
more complex decision-making by combining multiple conditions.
Syntax:
if (condition1)
{
// Code to be executed if condition1 is true
if (condition2)
{
// Code to be executed if both condition1 and condition2 are true
}
else
{
// Code to be executed if condition1 is true but condition2 is false
}
}
else
{
// Code to be executed if condition1 is false
}
Example:
#include <stdio.h>
int main()
{
int num;
printf("Enter a number: ");
scanf("%d", &num);
if (num > 0)
{
printf("Positive number.\n");
if (num % 2 == 0)
{
printf("Even number.\n");
}
else
{
printf("Odd number.\n");
}
}
else if (num == 0)
{
printf("Zero.\n");
}
else
{
printf("Negative number.\n");
}
return 0;
}
5. Switch Statements:
Switch statements allows to perform different actions based on the value of a specific expression or
variable. It provides a more concise and structured alternative to using multiple if-else statements.
Switch statements can be used for various scenarios, including menu selection, handling different cases,
and executing specific code blocks based on certain conditions.
Syntax:
switch(expression)
{
case constant1:
// Code to be executed if expression matches constant1
break;
case constant2:
// Code to be executed if expression matches constant2
break;
case constant3:
// Code to be executed if expression matches constant3
break;
// Add more cases as needed
default:
// Code to be executed if expression doesn't match any constant
}
Explanation:
- The switch expression is evaluated once, and its value is compared to each constant in the case
statements.
- If a case constant matches the value of the expression, the corresponding code block is executed.
- The break statement is used to exit the switch block. Without break, execution continues to the next
case until a break statement is encountered.
- The default case is optional and executes when the expression doesn't match any of the constants in
the preceding case statements.
Example 1
#include <stdio.h>
int main() {
int choice;
printf("Enter a number (1-3): ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("You chose option 1.\n");
break;
case 2:
printf("You chose option 2.\n");
break;
case 3:
printf("You chose option 3.\n");
break;
default:
printf("Invalid choice.\n");
}
return 0;
}
Example 2:
#include <stdio.h>
int main() {
char grade = 'B';
switch (grade) {
case 'A':
case 'a':
printf("Excellent!\n");
break;
case 'B':
case 'b':
printf("Good job!\n");
break;
case 'C':
case 'c':
printf("Passing grade.\n");
break;
default:
printf("Invalid grade.\n");
}
return 0;
}
In this example, both uppercase and lowercase letters are handled for each grade. the cases for 'A' and
'a', 'B' and 'b', etc., share the same code block.
The default case is optional but serves as a catch-all when none of the case constants match the
expression value.
Loop Statements:
Loop statements are defined as a block of statements which are repeatedly executed for a certain
number of times or until a particular condition is satisfied. When an identical task is to be executed for a
number of times loop statements are used. A loop allows execution of certain blocks of code repeatedly
until the conditional expression is true. It is important for a loop to have an ending condition, if not the
loop may run for indefinite number of time till it exhausts the memory of the system.
1. for loop:
The for loop allows to execute a block of statements for a given number of times. When the number of
repetitions is known in advance, for loop is used. Thus, this loop is also known as a determinate or
definite loop. It consists of three parts: initialization, condition, and increment/decrement.
Syntax:
// code to be executed
Example 1:
#include <stdio.h>
int main() {
int i;
for (i = 1; i <= 5; i++) {
printf("%d\n", i);
}
return 0;
}
Output:
1
2
3
4
5
Output:
Sum: 5050
Explanation:
In this example, the loop control variable i is initialized to 1, and the accumulator variable sum is
initialized to 0.
The condition i <= 100 specifies that the loop should continue as long as i is less than or equal to 100.
On each iteration, the value of i is added to the sum variable using the += operator.
The while loop is useful when you want to repeat a block of code based on a certain condition. It
evaluates the condition before executing the code block. Hence, It is a pre-test loop, meaning that the
condition is evaluated before the loop body is executed.
Syntax:
while (condition) {
// code to be executed
The condition is a logical expression that is checked before each iteration of the loop. If the condition
evaluates to true, the loop body will be executed. If the condition is false initially, the loop will not be
executed at all.
#include <stdio.h>
int main() {
int count = 1;
while (count <= 5) {
printf("%d\n", count);
count++;
}
return 0;
}
Output:
1
2
3
4
5
Explanation:
In this example, the variable count is initialized to 1. The condition count <= 5 is evaluated before each
iteration. As long as the condition is true, the loop body will execute. Inside the loop, the current value
of count is printed, and then count is incremented by 1. This process continues until count becomes 6, at
which point the condition becomes false, and the loop terminates.
#include <stdio.h>
int main() {
int sum = 0;
int number;
printf("Enter a number (0 to exit): ");
scanf("%d", &number);
while (number != 0) {
sum += number;
printf("Enter a number (0 to exit): ");
scanf("%d", &number);
}
printf("Sum: %d\n", sum);
return 0;
}
Output:
Enter a number (enter 0 to exit): 2
Sum = 2
Enter a number (enter 0 to exit): 4
Sum = 6
Explanation:
In this example, the program asks the user to enter a number repeatedly until they enter 0. Inside the
loop, the current number is added to the sum variable, and the user is asked again. When the user
enters 0, the loop condition becomes false, and the loop terminates. Finally, the program displays the
computed sum.
The do-while loop is similar to the while loop, but it evaluates the condition after executing the code
block. This ensures that the code block executes at least once, regardless of the condition. It is an exit-
controlled loop, meaning that the loop body is executed at least once before the condition is checked.
Syntax:
do {
// statements to be executed
} while (condition);
Explanation:
The block of code within the curly braces is executed first.
Then, the condition is checked.
If the condition is true, the loop body is executed again.
This process continues until the condition becomes false.
If the condition is initially false, the loop body is still executed at least once.
#include <stdio.h>
int main() {
int i = 1;
do {
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
#include <stdio.h>
int main() {
int n, sum = 0;
printf("Enter numbers (enter 0 to terminate): ");
do {
scanf("%d", &n);
sum += n;
} while (n != 0);
return 0;
Example Input:
Enter numbers (enter 0 to terminate): 2 4 6 0
Output:
Sum = 12
#include <stdio.h>
int main() {
int password, correctPassword = 1234;
do {
scanf("%d", &password);
if (password != correctPassword) {
printf("Access granted!");
return 0;
}
Example Input:
Output:
Access granted!
Syntax:
break;
#include <stdio.h>
int main() {
int i;
for (i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
printf("%d ", i);
}
return 0;
}
Output:
Explanation: In this example, the for loop runs from 1 to 10. However, when i becomes 5, the break
statement is encountered, and the loop terminates. As a result, only the numbers 1 to 4 are printed.
Switch Statement:
The break statement is also used within a switch statement to terminate the execution of the entire
switch block. When the break statement is encountered, the program exits the switch block and
continues execution from the statement immediately after the switch.
#include <stdio.h>
int main() {
int choice = 2;
switch (choice) {
case 1:
printf("Option 1 selected\n");
break;
case 2:
printf("Option 2 selected\n");
break;
case 3:
printf("Option 3 selected\n");
break;
default:
printf("Invalid option\n");
break;
return 0;
Output:
Option 2 selected
Explanation: In this example, the variable choice is set to 2. The switch statement checks the value of
choice and executes the corresponding case. When choice is 2, the "Option 2 selected" message is
printed, and the break statement causes the switch block to terminate.
Continue Statements:
Continue statements allows to skip the current iteration of a loop and proceed to the next iteration.
They are useful when you want to bypass specific parts of the loop's body and continue with the next
iteration based on certain conditions.
Syntax:
continue;
Explanation:
When the continue statement is encountered within a loop, it immediately terminates the current
iteration and transfers control back to the loop's condition or update statement. The subsequent
statements within the loop's body are skipped, and the next iteration begins.
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // Skip iteration when i = 3
}
printf("%d ", i);
}
return 0;
}
Output:
1245
Explanation: In this example, the loop prints the numbers from 1 to 5. However, when i is equal to 3, the
continue statement is encountered, and the loop skips that iteration, printing all other values.
#include <stdio.h>
int main() {
int i = 0;
while (i < 5) {
i++;
if (i == 2 || i == 4) {
return 0;
Output:
135
Explanation: In this example, the while loop prints the numbers from 1 to 5. However, when i is equal to
2 or 4, the continue statement is encountered, and the loop skips those iterations, printing all other
values.
go to statements:
The go to statement is used to alter the normal sequence of program execution by unconditionally
transferring the control to some other part of the program.
Syntax::
goto label;
Here, label is a user-defined identifier that acts as a target for the Go To statement. The label must be
defined before the Go To statement and the target statement must be labeled using syntax:
label statements;
Example
#include <stdio.h>
int main() {
int number;
if (number < 0) {
goto negative;
printf("Positive number.\n");
goto end;
negative:
printf("Negative number.\n");
end:
printf("Program ends.\n");
return 0;
Explanation:
In this example, the program asks the user to enter a number. If the number is negative, the program
uses the Go To statement to jump to the negative label, where it prints "Negative number." If the
number is positive, the program proceeds to the next statement after the Go To statement, printing
"Positive number." Finally, it reaches the end label, printing "Program ends."
An array is a collection of similar types of data items. Arrays allow the storage of multiple elements of
the same data type under a single variable name. To declare an array, we need to specify the data type
of the elements it will hold and the size of the array.
Syntax:
data_type array_name[array_size];
Examples:
int numbers[5]; This declares an array of integers named "numbers" with a size of 5
float grades[10]; This declares an array of floats named "grades" with a size of 10
char name[20]; This declares an array of characters named "name" with a size of 20
Initialization of Arrays:
Arrays can be initialized at the time of declaration using an initializer list, where each element is
specified within braces {}.The number of values in the initializer list should match the size of the array.
Examples:
int numbers[5] = {10, 20, 30, 40, 50}; This initializes the array "numbers" with the provided values
float grades[10] = {98.5, 92.0, 85.5, 77.5, 88.0}; This initializes the array "grades" with the provided
values
char name[20] = {'J', 'o', 'h', 'n'}; This initializes the array "name" with the provided characters
Array elements are accessed using indices starting from 0 to size-1. To access an element of an array,
use the array name followed by the index within square brackets [ ].
Examples:
You can modify the value of an array element by assigning a new value to it.
Example:
numbers [1] = 99; This modifies the value at index 1 to 99 hence resulting the array will be numbers[5] =
{10,99,30,40,50}
Array Size:
The size of an array determines the maximum number of elements it can hold. The size must be a
positive integer, and it can be a constant value or a variable.
Example:
int numbers[size]; This declares an array with a size determined by the variable "size"
Types of Array:
1. One Dimensional Array (1-D Array)
2. Two Dimensional Array (2-D Array) or Multi-Dimensional Array
Syntax:
datatype arrayName[size];
Example:
#include <stdio.h>
int main() {
int numbers[5]; this declares of an integer type array 'numbers' with a size of 5
int i;
numbers[i] = i + 1;
return 0;
Output:
Array elements: 1 2 3 4 5
Syntax:
datatype arrayName[size1][size2];
Columns
#include <stdio.h>
int main() {
int i, j;
matrix[i][j] = (i + 1) * (j + 1);
printf("Matrix elements:\n");
printf("\n");
return 0;
Output:
Matrix elements:
123
246
369
Initialization of String:
char name[ ] = {‘A’, ‘M’, ‘A’, ‘R’, ‘\O’};
This is also a valid initialization but C offers a special way and most used way of initialization.
char name[ ] = “AMAR”;
Arrays of Strings:
As string is itself an array of characters, an array of string can be considered as 2-D array of characters.
An array of strings is a collection of strings, where each element of the array is a string.
Syntax:
char array_name[rows][max_length];
Here, array_name is the name of the array, rows is the number of strings in the array, and max_length
represents the maximum length of any individual string.
Example:
char names[][20] = {
"John",
"Emma",
"Michael"
};
In this example, we have an array named names with three rows, each row representing a string
(student name). The maximum length of each string is set to 20 characters, which includes the null
character ('\0').
To access individual strings in an array of strings, we can use the row index to specify the desired string.
For example, to access the second string in the names array, we would use names[1].
Similarly, to access individual characters within a string, we can use the column index. For example, to
access the third character of the first string in the names array, we would use names[0][2].
We can modify or update individual strings in an array of strings using assignment statements or string
manipulation functions. For example, to change the first string in the names array to "Robert," we can
use the strcpy() function.
strcpy(names[0], "Robert");
Now, the first string in the names array will be "Robert" instead of "John."
Iterating Over an Array of Strings:
To iterate over all the strings in an array of strings, we can use nested loops. The outer loop iterates over
each row (string), and the inner loop iterates over each character within the string.
Example:
printf("%s\n", names[i]);
Output:
John
Emma
Michael
In C programming language we have built-in functions like strlen(), strcpy(), strcmp(), strcat(), strrev() etc
for string manipulations and these functions are defined in header file string.h. Hence we need to
include string.h in header file to use these string manipulating functions.
#include <string.h>
1. strlen() function:
The strlen() function is used to determine the length of a string. This function receives a string as an
argument and returns an integer which is the length of the string.
Syntax:
data_type variable_name = strlen(string);
Example:
#include <stdio.h>
#include <string.h>
int main() {
return 0;
Output:
Length of the string: 13
2. strcpy() function:
The strcpy() function copies one string to another. This function accepts two strings as parameters and
copies the second string into the first string, character by character including the null character ‘\O’.
Syntax:
strcpy(destination_string, source_string);
strcpy(s1,s2) means content of s2 string is copied to s1.
Example:
#include <stdio.h>
#include <string.h>
int main() {
char destination[20];
strcpy(destination, source);
return 0;
}
Output:
Copied string: Hello
3. strcat() function:
The strcat() function is used to concatenate (append) one string to the end of another. This function
takes two strings as arguments and stores the contents of the second string at the end of the first string.
Syntax:
strcat(string1, string2); meaning the content of string 2 is added at the end of string 1 (string 1 =
string1 + string 2)
Example:
#include <stdio.h>
#include <string.h>
int main() {
strcat(str1, str2);
return 0;
Output:
Concatenated string: Hello, world!
4. strcmp() function:
The strcmp() function is used to compare two strings. It returns 0 if the strings are equal, a positive value
if the first string is greater, and a negative value if the first string is smaller.
Syntax:
Example:
#include <stdio.h>
#include <string.h>
int main() {
if (result == 0) {
} else {
}
return 0;
Output:
First string is smaller
5. strrev() function:
The strrev() function is used to reverse a given string. It changes the order of characters within the
string, making the last character become the first, the second-to-last character become the second, and
so on. This string function modifies the original string directly.
Syntax:
strrev(string1);
Example:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World";
printf("Original String: %s\n", str);
strrev(str);
printf("Reversed String: %s\n", str);
return 0;
}
Output:
Original String: Hello World
Reversed String: dlroW olleH
6. strlwr() function:
The strlwr() function converts all the characters in a string to lowercase. It replaces uppercase letters
with their lowercase counterparts while leaving any non-alphabetic characters unchanged. This string
function modifies the original string directly.
Syntax:
stelwr(string1);
Example:
#include <stdio.h>
#include <string.h>
int main() {
Output:
Original String: Hello World
Lowercase String: hello world
7. strupr() function:
The strupr() function converts all the characters in a string to uppercase. It replaces lowercase letters
with their uppercase counterparts while leaving any non-alphabetic characters unchanged. This string
function modifies the original string directly.
Syntax:
strupr(string1);
Example:
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World";
printf("Original String: %s\n", str);
strupr(str);
printf("Uppercase String: %s\n", str);
return 0;
Output:
Original String: Hello World
Uppercase String: HELLO WORLD
Functions:
A function is defined as a self-contained block of statements that performs a particular specified job in a
program. Actually, it is a logical unit composed of a number of statements grouped together as a single
unit to perform a specific task or subtask of a program. It is often defined as a section of a program
performing a specific job or task. Function allows break down of a program into smaller, manageable
parts, making the code easier to understand, modify, and debug.
Advantages of functions:
1. Modularity and Code Reusability: Functions promote modularity by breaking down a program into
smaller, manageable chunks. These chunks of code can be reused in different parts of the program or
even in other programs, enhancing code reusability. Instead of duplicating code, we can call the same
function multiple times.
2. Abstraction: Functions allow to hide the implementation details of a specific task behind a function
name. This abstraction simplifies the overall code structure, making it easier to read, understand, and
maintain.
3. Readability and Maintainability: Using functions enhances the readability of the code. Functions
provide a way to group related instructions together, giving them a meaningful name that describes
their purpose. This makes the code more self-explanatory and easier to understand. Additionally,
functions promote code maintainability since any changes or bug fixes can be made in one place (the
function) instead of scattering them throughout the code-base.
4. Testing and Debugging: Functions enable easier testing and debugging of code. By isolating specific
functionalities within functions, testing and verifying the correctness of each individual function can be
carried down.
6. Distribution of work: By dividing specific functionalities to their respective functions the work of
building a program can be well divided between multiple programmers.
Syntax:
return_type function_name(arguments)
{
// Function body or implementation
Components of a function:
1. Function Definition: One or more statements that describes the specific task to be done by a function
is called function declaration. It consists of a function header, which defines function name, its return
type and its argument list, function body, which is a block enclosed in parenthesis.
3. Return_type: It specifies the type of value the function will return after execution. This can be any
valid C data type, such as int, float, char, void (no return value), etc. For example, if a function has return
type int, it returns an integer value after the execution to the main program. The “return” is a keyword
used at the end of the every function body to return specified value form the function. If a function has
“void” as return type, then there is no need to use “return” statement. The function of return statement
is to transfer the control back to the calling or main program after execution of return statement and to
return the value to the calling or main function.
4. Function_name: It is the name given to the function, which should be unique within the program.
Choose a meaningful name that reflects the purpose of the function.
5. Arguments: Function parameters or arguments are the means of communications between the
calling (main) function and the called function. Arguments are the inputs that a function expects in order
to perform its task. It consists of zero or more parameters (also known as arguments) that the function
accepts. Parameters are variables used to pass data into the function for processing. If the function
doesn't require any input, leave the parameter list empty or use void if no parameters are expected.
They can be classified into formal parameters and actual parameters.
5.1. Formal parameters: Formal parameters are variables declared in the function declaration or
definition. These parameters act as containers to receive values passed as arguments from the calling
function.
5.2. Actual Parameters: Actual parameters, also known as arguments, are the values or expressions
passed to a function when it is called. These values are assigned to the corresponding formal parameters
within the function.
Example:
#include <stdio.h>
int main() {
int a = 10;
float b = 3.14;
printMessage(a, b);
return 0;
6. Function body or implementation: It contains the actual code that is executed when the function is
called. This section can include variable declarations, statements, calculations, and even other function
calls.
7. Optional: Return statement: If the function has a return type other than void, it should include a
return statement to provide the result of the function. The return statement specifies the value to be
sent back to the calling code.
Example:
#include <stdio.h>
void greet() {
int main() {
return 0;
Types of functions:
According to origin functions can be divided into two categories:
1. Library functions (built in functions)
Library functions are predefined functions that come with the C programming language. For example,
printf(), scanf(), strlen() etc
2. User defined functions
User-defined functions are created by the programmer to perform specific tasks. They provide flexibility
and allow for code reuse.
Example:
#include <stdio.h>
return a + b;
}
int main() {
return 0;
1. Void Functions:
Void functions, as the name suggests, do not return any value. They are primarily used for performing
actions or tasks without needing to return a result.
Syntax:
void function_name() {
// Function body
Example:
#include <stdio.h>
void greet() {
int main() {
return 0;
Syntax:
return_type function_name() {
// Function body
return value;
}
Example:
#include <stdio.h>
int getRandomNumber() {
int main() {
return 0;
Syntax:
return_type function_name(argument_type1 arg1, argument_type2 arg2, ...) {
// Function body
return value;
Example:
#include <stdio.h>
return a + b;
int main() {
int result = sum(5, 7); // Calling the value-returning function with arguments
return 0;
// Function body
Example:
#include <stdio.h>
int main() {
return 0;
Syntax:
return_type function_name(data_type argument);
Example:
#include <stdio.h>
int temp = a;
a = b;
b = temp;
int main() {
swap(x, y);
Output:
Before swap: x = 10, y = 20
After swap: x = 10, y = 20
Explanation:
In the above example, the swap function is called by passing the values of x and y. Inside the swap
function, the parameters a and b are assigned the values of x and y respectively. However, any
modifications made to a and b do not affect the values of x and y outside the function. Hence, the values
of x and y remain unchanged after the swap.
Syntax:
return_type function_name(data_type *argument); // here use of “*” gives address of the argument
Example:
#include <stdio.h>
*a = *b;
*b = temp;
int main() {
swap(&x, &y);
return 0;
Output:
Before swap: x = 10, y = 20
After swap: x = 20, y = 10
Explanation:
In the above example, the swap function is called by passing the addresses of x and y using the &
(address-of) operator. Inside the swap function, the parameters a and b are pointers to integers. By
dereferencing these pointers using the * (dereference) operator, we can access and modify the values of
x and y. As a result, the values of x and y are swapped successfully.
Example:
#include <stdio.h>
int factorial(int n)
if (n == 0)
return 1;
else
int main()
int num;
scanf("%d", &num);
return 0;
}
Difference between Recursion and Iteration:
A function calls to itself until certain condition is No function call is required as repetition is done
meet through statements.
Recursion can be used when a problem can be It is not necessary to define a problem in term of
defined in term of its previous result. its previous result.
Two conditions must be meet to solve a problem No two conditions are required to solve a
with recursion. problem with iteration.
May consume more memory and stack space for Uses a fixed amount of memory and stack space.
deeply nested function calls.
May be harder to understand and debug for Usually easier to understand and debug.
complex recursive algorithms.
Types Of variables:
1. Local Variables (Internal variables)
These types of variables are always declared within a function and are local to the particular function or
block they are declared within. As local variables are declared within the body of the function, they are
only accessible from same block of code or functions only. These variables are not accessible by
functions they are not declared within. The local variables are created when the function is called and
destroyed once the function is exited. They are used to store temporary data that is needed only for the
duration of that block.
Exxample:
void function() {
Example:
#include <stdio.h>
void function() {
int main() {
function();
return 0;
3. Static Variables
Static variables are declared inside a function with the static keyword and have local scope, similar to
regular local variables. However, unlike local variables, static variables retain their values even after the
function execution is completed. Static variables are initialized only once, and their value is preserved
across multiple function calls.
Example:
#include <stdio.h>
void function() {
count++;
printf("%d\n", count);
int main() {
function(); // Output: 1
function(); // Output: 2
function(); // Output: 3
return 0;
}
4. Register Variables
Register variables are declared with the register keyword and are used to suggest the compiler to store
them in the CPU registers for faster access. Register variables have local scope and behave similarly to
other local variables, but with the potential for improved performance.
Example:
#include <stdio.h>
void function() {
int main() {
function(); // Output: 0 1 2 3 4 5 6 7 8 9
return 0;
Syntax:
void functionName(int array[], int size);
While calling a function that expects an array as an argument, simply provide the name of the array as
the corresponding argument.
Example:
functionName(numbers, 5);
Example:
#include <stdio.h>
int sum = 0;
sum += array[i];
return sum;
}
int main() {
return 0;
int main() {
displayString(message);
return 0;
Structure:
A structure is a user-defined data type that can hold multiple data members of different types.
Structures provide a way to group different variables of different types together into a single unit.
Structures allow to define own data types that can contain multiple elements, such as integers, floats,
characters, and even other structures.
Syntax:
struct structure_name {
data_type member1;
data_type member2;
// more members...
};
The struct keyword is used to define a new structure, followed by the name for the structure. Inside the
curly braces, declaration of the members of the structure, each with its own data type is done.
Example:
struct Person {
char name[50];
int age;
float height;
};
struct Student {
char name[50];
int rollNumber;
float marks;
};
int main() {
scanf("%s", student1.name);
printf("Enter roll number: ");
scanf("%d", &student1.rollNumber);
scanf("%f", &student1.marks);
printf("\nStudent Details\n");
Size of Structure:
The size of a structure is the sum of the sizes of its individual members. To determine the size of a
structure, use the sizeof operator.
Syntax:
sizeof(structure_name)
Array of Structure:
An array of structures in C can be defined as the collection of multiple structure variables where each
variable contains information about different entities. The array of structures in C are used to store
information about multiple entities of different data types. The array of structures is also known as the
collection of structures.
Example:
#include <stdio.h>
struct student {
int rollNumber;
char name[50];
float marks;
};
int main() {
struct student class[3];
class[0].rollNumber = 1;
strcpy(class[0].name, "John");
class[0].marks = 85.5;
class[1].rollNumber = 2;
strcpy(class[1].name, "Alice");
class[1].marks = 92.0;
class[2].rollNumber = 3;
strcpy(class[2].name, "Bob");
class[2].marks = 78.25;
return 0;
}
Output:
Student 1
Roll Number: 1
Name: John
Marks: 85.50
Student 2
Roll Number: 2
Name: Alice
Marks: 92.00
Student 3
Roll Number: 3
Name: Bob
Marks: 78.25
Nested Structure:
When a structure contains another structure, it is called a nested structure. For example, we have two
structures named Address and Employee. To make Address nested to Employee, we have to define
Address structure before and outside Employee structure and create an object of Address structure
inside Employee structure.
Syntax:
struct OuterStructure {
// Outer structure members
// ...
struct InnerStructure {
// Inner structure members
// ...
};
};
Example:
struct Student {
char name[50];
int rollNumber;
struct Marks {
int math;
int physics;
int chemistry;
} marks;
};
Another Example:
#include<stdio.h>
struct Address {
char HouseNo[25];
char City[25];
char PinCode[25];
};
struct Employee {
int Id;
char Name[25];
float Salary;
struct Address Add;
};
void main() {
int i;
struct Employee E;
printf("\n\tEnter Employee Id : ");
scanf("%d",&E.Id);
printf("\n\tEnter Employee Name : ");
scanf("%s",&E.Name);
printf("\n\tEnter Employee Salary : ");
scanf("%f",&E.Salary);
printf("\n\tEnter Employee House No : ");
scanf("%s",&E.Add.HouseNo);
printf("\n\tEnter Employee City : ");
scanf("%s",&E.Add.City);
printf("\n\tEnter Employee House No : ");
scanf("%s",&E.Add.PinCode);
printf("\nDetails of Employees");
printf("\n\tEmployee Id : %d",E.Id);
printf("\n\tEmployee Name : %s",E.Name);
printf("\n\tEmployee Salary : %f",E.Salary);
printf("\n\tEmployee House No : %s",E.Add.HouseNo);
printf("\n\tEmployee City : %s",E.Add.City);
printf("\n\tEmployee House No : %s",E.Add.PinCode);
}
Output :
Enter Employee Id : 101
Enter Employee Name : Suresh
Enter Employee Salary : 45000
Enter Employee House No : 4598/D
Enter Employee City : Delhi
Enter Employee Pin Code : 110056
Details of Employees
Employee Id : 101
Employee Name : Suresh
Employee Salary : 45000
Employee House No : 4598/D
Employee City : Delhi
Employee Pin Code : 110056
Union:
A union in C is a user-defined data type that allows storing different types of data in the same memory
location. Unlike structures, which allocate memory for each member individually, a union allocates
memory for its largest member. In union, members will share the memory location. If we try to make
changes in any of the members then it will be reflected to the other member as well. The size of a union
is determined by the size of its largest member.
Definition:
A union is defined using the union keyword, followed by a name for the union. It is similar to a structure
declaration, but instead of listing members, we only define the types that can be stored within the
union.
Syntax:
union union_name {
member1_type member1;
member2_type member2;
...
memberN_type memberN;
};
Declaration:
After defining a union, we can declare variables of that union type. Variables can be declared either
globally or locally within functions.
union myUnion {
int i;
float f;
char c;
};
void someFunction() {
union myUnion {
int i;
float f;
char c;
};
Example:
union myUnion {
int i;
float f;
char c;
};
int main() {
union myUnion u;
u.i = 10; // Accessing 'i' member
u.f = 3.14; // Accessing 'f' member
u.c = 'A'; // Accessing 'c' member
return 0;
}
Size of Union:
The size of a union is determined by the size of its largest member. It ensures that the union can
accommodate the largest member's storage requirements.
Syntax:
sizeof(union union_name);
Use Cases:
Unions are useful in scenarios where memory efficiency is a concern, and different types of data need to
be stored in the same memory location. Common use cases for unions include handling variant types,
implementing bit fields, or optimizing memory usage in specific situations.
union variant {
int intValue;
float floatValue;
char* stringValue;
};
if (v.intValue) {
printf("%d\n", v.intValue);
} else if (v.floatValue) {
printf("%f\n", v.floatValue);
} else if (v.stringValue) {
printf("%s\n", v.stringValue);
}
}
int main() {
union variant v1;
v1.intValue = 10;
printVariant(v1);
return 0;
}
Output:
Variant value: 10
Variant value: 3.140000
Variant value: Hello
Difference between Structure And Union:
Structure Union
Definition A structure is a user-defined data type that A union is a user-defined data type that
groups related variables of different data allows different variables to be stored in
types together. the same memory location, sharing the
same memory space.
Memory Each member of a structure has its own Members of a union share the same
Allocation memory space, and the total memory memory space, and the memory allocated
allocated is the sum of memory spaces is equal to the size of the largest member.
required by each member.
Memory Usage Structure uses memory for all its members, Union only uses memory for the largest
even if they are not currently being member, and the memory is reused for
accessed. different members as needed.
Member Access Members in a structure can be accessed Only one member of a union can be
simultaneously or individually. accessed at a time.
Size The size of a structure is the sum of the sizes The size of a union is equal to the size of its
of its members, with additional padding for largest member
alignment.
Storage Structures require separate memory space Unions provide a single memory space that
for each member. is shared among its members
Pointer
A pointer is a special type of variable as it contains a memory address instead of values. A pointer
variable is declared with specific data type, like any other normal variable, so that it will work only with
memory address of a given type. A pointer stores the memory address of the another variable. Pointers
enable to indirectly access and manipulate data stored in memory. By using pointers, we can
dynamically allocate memory, pass arguments by reference, and build complex data structures.
Examples:
int *ptr; // Declaring an integer pointer named ptr
Pointer Declaration:
A pointer declaration is done by specifying the data type of the variable it points to.
Syntax:
datatype *pointer_name;
Example:
#include <stdio.h>
int main() {
return 0;
Output:
Value of 'number': 42
Value of 'pointer': 0x7ffeed41edac
Dereferenced value of 'pointer': 42
Address Operator:
The operator ‘&‘ is also known as address operator as we can represent the address of the variable using
this operator. The address operator (&) is used to obtain the memory address of a variable. It allows to
access and manipulate the memory location where a variable is stored. Thus &x denoted the address
pointed by the variable a where the value of the variable ‘a’ is stored.
Example:
#include <stdio.h>
int main() {
return 0;
Output:
Address of 'number': 0x7ffeed41edac
Syntax/Example:
int num = 10; // Declare and initialize an integer variable
int *ptr; // Declare an integer pointer
ptr = # // Assign the memory address of num to ptr
Bad Pointer:
When a pointer variable is first declared, it does not have a valid address. A bad pointer refers to a
pointer that either points to an invalid memory address or has not been initialized correctly. Hence, a
bad pointer is a pointer that points to an invalid memory address or has not been initialized at all. It can
cause program crashes or unexpected behavior.
Example:
#include <stdio.h>
int main() {
return 0;
Void Pointer:
A void pointer is a special type of pointer that can point to objects of any data type. It is commonly used
when the type of data being pointed to is unknown or when working with generic functions. The void
pointer, also known as a generic pointer, provides flexibility and allows for dynamic type casting.
Syntax:
To declare a void pointer, weyou use the keyword "void" followed by an asterisk (*) and a variable
name. This creates a pointer variable that can hold the address of any data type.
void *ptr;
Example:
int num = 10;
float pi = 3.14;
void *ptr;
Example:
int num = 10;
Null Pointer:
A null pointer is a special pointer value that points to no valid memory address. It is commonly used to
indicate the absence of a meaningful value or the end of a data structure. It is represented by the special
value "NULL" or "0". When a pointer is assigned a null value, it indicates that the pointer does not
currently point to any meaningful data.
Syntax:
<datatype> *<pointer_name> = NULL;
int *ptr = NULL;
By performing arithmetic operations on pointers, you can access and manipulate data in an efficient
manner.
1. Addition:
int arr[5] = {1, 2, 3, 4, 5};
2. Subtraction:
int arr[5] = {1, 2, 3, 4, 5};
Explanation:
In this example, ptr is a pointer to the last element of the array arr. By subtracting an offset from the
pointer, we can access elements at different indices of the array in reverse order. The subtraction
operation ptr - 2 moves the pointer two positions back, allowing us to access the element at index 2.
int main() {
int *ptr = numbers; // Assign the pointer to the first element of the array
return 0;
Explanation:
Initially, the pointer ptr points to the first element of the array. After incrementing it with ptr++, the
pointer now points to the second element, and accessing *ptr gives us the value 20. Similarly,
decrementing the pointer with ptr-- returns to the first element.
C programming language allows the use of a pointer that points to other pointers and these m in term
points to the data. A pointer to pointer, also known as a double pointer, is a pointer variable that stores
the memory address of another pointer variable. It allows us to indirectly access or modify the value of a
pointer.
Syntax:
datatype **ptr;
Example:
#include <stdio.h>
**ptr = 20;
int main() {
modifyValue(ptr2);
return 0;
Output:
Before modification: 10
After modification: 20
Explanation:
In this example, we define a function modifyValue that takes a pointer to pointer as an argument.
Inside the function, we dereference the double pointer (**ptr) and assign the value 20 to the variable it
points to.
In the main function, we declare num, ptr1, and ptr2.
We pass the address of ptr1 (ptr2) to the modifyValue function.
The function modifies the value of num indirectly by using the pointer to pointer.
The output shows that the value of num changes from 10 to 20.
Array Of Pointers:
An array is a collection of elements of the same type, which are stored in contiguous memory locations.
On the other hand, a pointer is a variable that stores the memory address of another variable. When we
combine arrays and pointers, we can create an array of pointers, which is an array where each element
is a pointer to another variable.
Syntax:
data_type *array_name[size];
Example:
#include <stdio.h>
int main() {
return 0;
Output:
Values using array of pointers:
Value of a: 10
Value of b: 20
Value of c: 30
Explanation:
In this example, we declare an array of three integer pointers, ptr_array.
We assign the addresses of variables a, b, and c to the elements of the array using the & (address-of)
operator.
To access the values stored in a, b, and c, we use the * (dereference) operator with the array elements.
By dereferencing the pointers, we obtain the actual values stored in the variables.
The concept of dynamic memory allocation enable the programmer to allocate the memory at runtime.
This flexibility enables efficient memory utilization, especially when you don't know the exact amount of
memory needed beforehand. There are four essential functions used for dynamic memory allocations:
1. malloc ()
2. calloc ()
3. realloc ()
4. free ()
Differences between static memory allocation and dynamic memory allocation:
1. malloc () function:
malloc function is used for dynamic memory allocation, allowing programmers to allocate memory at
runtime. This feature gives flexibility and efficiency to the code by dynamically adjusting the memory
requirements. The malloc function allocated a single block of requested memory. It doesn’t initialize
memory at execution time so it has garbage value initially and it returns NULL if memory is not
sufficient. The function malloc() is defined in the stdlib.h header file, so it's important to include this
header at the beginning of your program.
Syntax:
ptr = (cast_type*) malloc(size);
Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
int* numPtr;
numPtr = (int*)malloc(sizeof(int));
if (numPtr == NULL) {
return 1;
*numPtr = 42;
free(numPtr);
return 0;
Output:
The value of numPtr: 42
Explanation:
In this example, we allocate memory to store an integer variable using malloc().
We assign the allocated memory to the numPtr pointer.
It's important to check if malloc() returns a valid pointer. If it returns NULL, it means the memory
allocation failed, and we handle the error accordingly.
We can access and modify the allocated memory using the dereference operator *.
After we are done using the allocated memory, we should release it using the free() function to prevent
memory leaks.
2. calloc () function:
The calloc function allocates multiple blocks of requested memory. It initially initializes all bytes to zero
and return NULL if memory is not sufficient. The calloc() function is used to dynamically allocate memory
for an array of elements. The function calloc() is also defined in the stdlib.h header file, so it's important
to include this header at the beginning of your program.
Syntax:
ptr = (cast_type*) calloc(num, size);
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *message;
if (message == NULL) {
return 1;
printf("%s\n", message);
free(message);
return 0;
}
Explanation:
The main() function begins by declaring a character pointer, message.
Memory allocation is performed using the calloc() function: message = (char*)calloc(50, sizeof(char));.
We allocate memory for a string of 50 characters, including the null terminator.
sizeof(char) determines the size of each character in bytes.
The return value of calloc() is assigned to the message pointer.
If memory allocation fails, calloc() returns NULL.
To ensure that memory allocation was successful, we check if message is NULL. If so, an error message is
displayed, and the program exits.
The strcpy() function is used to copy the string "Hello, calloc!" into the allocated memory.
Finally, the message is displayed using printf(), and the allocated memory is freed using free().
3. realloc() function:
If memory allocated is not sufficient , we can reallocate the memory using realloc function.The realloc()
function allows you to resize an already allocated memory block. In short, it changes the previously
allocated memory size. The realloc() function is used to dynamically reallocate memory for a previously
allocated block. It allows us to resize the memory block, either making it larger or smaller, while
preserving its existing data. This capability is particularly useful when we need to modify the size of an
array or structure during runtime.
Syntax:
ptr = realloc(ptr, newSize);
printf("Original Array:\n");
arr[i] = i + 1;
printf("\n\nExpanded Array:\n");
return 0;
}
Explanation:
In this example, we allocate memory for an array of 5 integers using malloc(). Then, we assign values to
the array elements and display them. Next, we use realloc() to increase the size of the array to 10.
4. free() function:
The memory allocated by malloc or calloc or realloc functions must be released or freed for further use.
The free() function is used to deallocate memory previously allocated by malloc(), calloc(), or realloc(). It
releases the memory back to the system, making it available for future use.
Syntax:
free(ptr);
Example:
int* numbers;
free(numbers)
Data Files:
A collection of data which is stored on a secondary device like a hard disk is known as a file or data file.
This enables us to read data from files into your program or write data from your program into files.
Text Files:
Text files store data in plain text format, where each character is represented using its corresponding
ASCII value. Text files are human-readable and can be opened with a text editor (e.g., Notepad, Sublime
Text).
Binary Files:
Binary files store data in a format that is not human-readable. They store data in the same format as it is
represented in memory. Binary files are commonly used for storing complex data structures or large
amounts of data. When working with binary files, it is crucial to ensure that the file is opened and read
or written in the same format it was originally stored to avoid data corruption or inconsistencies.
File handling is an essential aspect of programming, allowing us to read and write data from and to files.
In C programming, file handling operations involve opening, reading, writing, and closing files.
1. Opening a file: Before performing any operations on a file, it must be opened. The fopen() function is
used to open a file with a specified mode (read, write, append, etc.).
Syntax:
FILE *filePointer;
filePointer = fopen("filename", "mode");
Example:
FILE *fp;
fp = fopen("data.txt", "r");
Mode Description
“r” It opens an existing file for reading purpose only.
“w” It opens a new file for writing purpose, If the filename doesn’t exists it will be
created and if the file exists, then its content is replaced by the new contents.
“a” It is used to append to an existing file, It the file doesn’t exists, a new file is created
“r+” It opens an existing file for reading and writing. It indicated the file must be read
before writing.
“w+” It opens a new file for reading and writing. If a file with given filename exists then it
is deleted and new file is created.
“a+” It opens an existing file for reading and appending.
2. Closing a file: After finishing operations on a file, it is essential to close it using the fclose() function.
This ensures that any pending operations are completed and resources are released.
Syntax:
fclose(filePointer);
Example:
fclose(fp);
Syntax:
int fgetc(FILE *stream);
Example:
FILE *file = fopen("data.txt", "r");
int ch;
printf("%c", ch);
}
fclose(file);
3.2 Reading Strings(fgets): If we want to read a string from a file, we can use the fgets() function. It
reads a line from the file.
Syntax:
char *fgets(char *str, int size, FILE *stream);
Example:
#include <stdio.h>
int main() {
if (file != NULL) {
char str[100];
fclose(file);
return 0;
Example:
FILE *file = fopen("data.txt", "r");
fclose(file);
4. Writing to a file:
4.1 Writing Characters(fputc): This function is used to write a character to a file.
Syntax
int fputc(int character, FILE *stream);
Example:
#include <stdio.h>
int main() {
if (file != NULL) {
char ch = 'A';
fclose(file);
return 0;
4.2 Writing string to a file (fputs): This function is used to write a string to a file.
Syntax:
int fputs(const char *str, FILE *stream);
Example:
#include <stdio.h>
int main() {
if (file != NULL) {
fclose(file);
return 0;
4.3 Writing formatted data to ta file (fprintf): This function is used to write any formatted data to a file.
Example:
#include <stdio.h>
int main() {
fclose(file);
return 0;
Creating File:
C programming allows programmer to create a file to write the file with information to be stored for
future use or manipulation. To use this function we need to include stdio.h file handing library at the top
of our program.
Syntax:
FILE *filePointer;
filePointer = fopen("filename.txt", "w");
Example:
#include <stdio.h>
int main() {
FILE *filePointer;
if (filePointer == NULL) {
fclose(filePointer);
return 0;