0% found this document useful (0 votes)
3 views35 pages

C Prog Notes

#define is a preprocessor directive in C used to define macros, which can represent constants or functions. The document also covers multidimensional arrays, including 2D and 3D arrays, various algorithms such as linear and binary search, sorting algorithms like bubble sort, insertion sort, and selection sort, as well as methods for calculating factorials and Fibonacci series.

Uploaded by

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

C Prog Notes

#define is a preprocessor directive in C used to define macros, which can represent constants or functions. The document also covers multidimensional arrays, including 2D and 3D arrays, various algorithms such as linear and binary search, sorting algorithms like bubble sort, insertion sort, and selection sort, as well as methods for calculating factorials and Fibonacci series.

Uploaded by

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

#define in C

In C programming, #define is a preprocessor directive that is used to define macros. The


macros are the identifiers defined by #define which are replaced by their value before
compilation. We can define constants and functions like macros using #define. The generics
in C are also implemented using the #define preprocessor directive along with _Generic.

Syntax of C #define
The syntax of #define preprocessor directive in C is:

For Defining Constants


#define MACRO_NAME value

For Defining Expressions


#define MACRO_NAME (expression within brackets)

For Defining Expression with Parameters


Arguments passed in the macros can be used in the expression.
#define MACRO_NAME(ARG1, ARG2,..) (expression within brackets)

Example 1:

In the below example, we have defined a macro ‘PI’ and assigned it a


constant value which we can use later in the program to calculate the area
of a circle.
// C Program to illustrate how to use #define to declare
// constants
#include <stdio.h>

// Defining macros with constant value


#define PI 3.14159265359

int main()
{

​ int radius = 21;


​ int area;

​ // Using macros to calculate area of circle


​ area = PI * radius * radius;
​ printf("Area of Circle of radius %d: %d", radius, area);

​ return 0;
}

Multidimensional Arrays in C – 2D and 3D


Arrays
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.

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.

3D Array Traversal in C

To access an elements in 3D array, we use three indexes. One for depth,


one for row and one for column.

arr_name[d][i][j]
where, d, i and j are the indexes for depth (representing a specific 2D
array.), the row within that 2D array, and the column within that 2D array
respectively.

To traverse the entire 3D array, you need to use three nested loops: an
outer loop that goes through the depth (or the set of 2D arrays), a middle
loop goes through the rows of each 2D array and at last an inner loop
goes through each element of the current row.

Finding factorial:
// C program to find factorial of given number
#include <stdio.h>

// function to find factorial of given number


int factorial(int n)
{
if (n == 0)
return 1;
return n * factorial(n - 1);
}

int main()
{
int num = 5;
printf("Factorial of %d is %d", num, factorial(num));
return 0;
}

Program to print first N terms of Fibonacci Series:


#include <stdio.h>

// Function to print fibonacci series


void printFib(int n) {
if (n < 1) {
printf("Invalid Number of terms\n");
return;
}

// When number of terms is greater than 0


int prev1 = 1;
int prev2 = 0;

printf("%d ", prev2);

// If n is 1, then we do not need to


// proceed further
if (n == 1)
return;

printf("%d ", prev1);

// Print 3rd number onwards using


// the recursive formula
for (int i = 3; i <= n; i++) {
int curr = prev1 + prev2;
prev2 = prev1;
prev1 = curr;
printf("%d ", curr);
}
}

// Driver code
int main() {
int n = 9;
printFib(n);
return 0;
}

Linear Search Algorithm


In Linear Search, we iterate over all the elements of the array and check if
it the current element is equal to the target element. If we find any
element to be equal to the target element, then return the index of the
current element. Otherwise, if no element is equal to the target element,
then return -1 as the element is not found. Linear search is also known as
sequential search.

// C code to linearly search x in arr[].

#include <stdio.h>

int search(int arr[], int N, int x)


{
for (int i = 0; i < N; i++)
if (arr[i] == x)
return i;
return -1;
}

// Driver code
int main(void)
{
int arr[] = { 2, 3, 4, 10, 40 };
int x = 10;
int N = sizeof(arr) / sizeof(arr[0]);

// Function call
int result = search(arr, N, x);
(result == -1)
? printf("Element is not present in array")
: printf("Element is present at index %d", result);
return 0;
}

Binary Search

Conditions to apply Binary Search Algorithm in a


Data Structure
To apply Binary Search algorithm:

●​ The data structure must be sorted.

●​ Access to any element of the data structure should take

constant time.

Below is the step-by-step algorithm for Binary Search:


●​ Divide the search space into two halves by finding the middle

index “mid”.

●​ Compare the middle element of the search space with the key.

●​ If the key is found at middle element, the process is

terminated.

●​ If the key is not found at middle element, choose which half

will be used as the next search space.

○​ If the key is smaller than the middle element,

then the left side is used for next search.

○​ If the key is larger than the middle element,

then the right side is used for next search.

●​ This process is continued until the key is found or the total

search space is exhausted.

// Iterative method

#include <stdio.h>

int binarySearch(int array[], int x, int low, int high)


{
​ // Repeat until the pointers low and high meet each
​ // other
​ while (low <= high) {
​ ​ int mid = low + (high - low) / 2;

​ ​ if (array[mid] == x)
​ ​ ​ return mid;

​ ​ if (array[mid] < x)
​ ​ ​ low = mid + 1;

​ ​ else
​ ​ ​ high = mid - 1;
​ }

​ return -1;
}

int main( )
{
​ int array[] = { 2, 4, 5, 7, 14, 17, 19, 22 };
​ int n = sizeof(array) / sizeof(array[0]);
​ int x = 22;
​ int result = binarySearch(array, x, 0, n - 1);
​ if (result == -1)
​ ​ printf("Not found");
​ else
​ ​ printf(" %d", result);
​ return 0;
}

Recursive code

// C program to implement recursive Binary Search


#include <stdio.h>

// A recursive binary search function. It returns


// location of x in given array arr[low..high] is present,
// otherwise -1
int binarySearch(int arr[], int low, int high, int x)
{
if (high >= low) {
int mid = low + (high - low) / 2;

// If the element is present at the middle


// itself
if (arr[mid] == x)
return mid;

// If element is smaller than mid, then


// it can only be present in left subarray
if (arr[mid] > x)
return binarySearch(arr, low, mid - 1, x);

// Else the element can only be present


// in right subarray
return binarySearch(arr, mid + 1, high, x);
}

// We reach here when element is not


// present in array
return -1;
}

// Driver code
int main()
{
int arr[] = { 2, 3, 4, 10, 40 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 10;
int result = binarySearch(arr, 0, n - 1, x);
if (result == -1) printf("Element is not present in array");
else printf("Element is present at index %d", result);
return 0;
}

Linear Search Binary Search

In linear search input data need In binary search input data need
not to be in sorted. to be in sorted order.

It is also called half-interval


It is also called sequential search.
search.

The time complexity of linear The time complexity of binary


search O(n). searchO(log n).
Multidimensional array can be Only single dimensional array is
used. used.

Linear search performs equality Binary search performs ordering


comparisons comparisons

It is less complex. It is more complex.

It is very slow process. It is very fast process.

Bubble Sort
Bubble Sort is the simplest sorting algorithm that works by repeatedly
swapping the adjacent elements if they are in the wrong order. This
algorithm is not suitable for large data sets as its average and
worst-case time complexity are quite high.

●​ We sort the array using multiple passes. After the first pass,

the maximum element goes to end (its correct position). Same

way, after second pass, the second largest element goes to

second last position and so on.

●​ In every pass, we process only those elements that have

already not moved to correct position. After k passes, the


largest k elements must have been moved to the last k

positions.

●​ In a pass, we consider remaining elements and compare all

adjacent and swap if larger element is before a smaller

element. If we keep doing this, we get the largest (among the

remaining elements) at its correct position.

// Optimized implementation of Bubble sort


#include <stdbool.h>
#include <stdio.h>

void swap(int* xp, int* yp){


int temp = *xp;
*xp = *yp;
*yp = temp;
}

// An optimized version of Bubble Sort


void bubbleSort(int arr[], int n){
int i, j;
bool swapped;
for (i = 0; i < n - 1; i++) {
swapped = false;
for (j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(&arr[j], &arr[j + 1]);
swapped = true;
}
}

// If no two elements were swapped by inner loop,


// then break
if (swapped == false)
break;
}
}

// Function to print an array


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

int main(){
int arr[] = { 64, 34, 25, 12, 22, 11, 90 };
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}

Insertion Sort Algorithm


Insertion sort is a simple sorting algorithm that works by iteratively
inserting each element of an unsorted list into its correct position in a
sorted portion of the list. It is like sorting playing cards in your hands.
You split the cards into two groups: the sorted cards and the unsorted
cards. Then, you pick a card from the unsorted group and put it in the
right place in the sorted group.

●​ We start with the second element of the array as the first

element is assumed to be sorted.

●​ Compare the second element with the first element if the

second element is smaller then swap them.

●​ Move to the third element, compare it with the first two

elements, and put it in its correct position

●​ Repeat until the entire array is sorted.

// C program for implementation of Insertion Sort


#include <stdio.h>
/* Function to sort array using insertion sort */
void insertionSort(int arr[], int n)
{
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;

/* Move elements of arr[0..i-1], that are


greater than key, to one position ahead
of their current position */
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}

/* A utility function to print array of size n */


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

// Driver method
int main()
{
int arr[] = { 12, 11, 13, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);

insertionSort(arr, n);
printArray(arr, n);

return 0;
}

/* This code is contributed by Hritik Shah. */

Selection Sort
Selection Sort is a comparison-based sorting algorithm. It sorts an
array by repeatedly selecting the smallest (or largest) element from the
unsorted portion and swapping it with the first unsorted element. This
process continues until the entire array is sorted.

1.​ First we find the smallest element and swap it with the first

element. This way we get the smallest element at its correct

position.

2.​ Then we find the smallest among remaining elements (or

second smallest) and swap it with the second element.

3.​ We keep doing this until we get all elements moved to correct

position.

// C program for implementation of selection sort


#include <stdio.h>

void selectionSort(int arr[], int n) {


for (int i = 0; i < n - 1; i++) {

// Assume the current position holds


// the minimum element
int min_idx = i;

// Iterate through the unsorted portion


// to find the actual minimum
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_idx]) {

// Update min_idx if a smaller element is found


min_idx = j;
}
}

// Move minimum element to its


// correct position
int temp = arr[i];
arr[i] = arr[min_idx];
arr[min_idx] = temp;
}
}

void printArray(int arr[], int n) {


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

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);

printf("Original array: ");


printArray(arr, n);

selectionSort(arr, n);

printf("Sorted array: ");


printArray(arr, n);

return 0;
}

Square Root of a Number

[Naive Approach] Using a loop

As, we know that square root of a positive integer is always greater than
or equal to one. So we start iterating from 1 and calculate the square of
each number. We continue the iteration until we reach to an integer whose
square is greater than the given integer, then the integer just before it will
be our answer.
// C program to find the square root of
// given integer using a loop

#include <stdio.h>
int floorSqrt(int n) {

// Start iteration from 1 until the


// square of a number exceeds n
int res = 1;
while (res * res <= n) {
res++;
}

// return the largest integer whose


// square is less than or equal to n
return res - 1;
}

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

[Expected Approach] Using Binary Search

The square root of an integer follows a monotonic pattern, because as we


increase any number, it’s square also increases. If the square of a number
is greater than given integer, then square root will definitely exist before
this number. Conversely, if the square of a number is less than or equal to
n, then either this number is the square root or it lies after this number.​
Therefore, we can use binary search to find the square root of n. Initial
search space will be 1 to the given integer itself, because square root of
any positive integer always exists within this range.

// C program to find the square root of given integer


// using binary search

#include <stdio.h>

int floorSqrt(int n) {

// Initial search space


int lo = 1, hi = n;
int res = 1;

while (lo <= hi) {


int mid = lo + (hi - lo) / 2;

// If square of mid is less than or equal to n


// update the result and search in upper half
if (mid * mid <= n) {
res = mid;
lo = mid + 1;
}

// If square of mid exceeds n,


// search in the lower half
else {
hi = mid - 1;
}
}

return res;
}

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

Array Reverse – Complete Tutorial


Given an array arr[], the task is to reverse the array. Reversing an array
means rearranging the elements such that the first element becomes the
last, the second element becomes second last and so on.

[Naive Approach] Using a temporary array – O(n) Time and O(n)


Space

The idea is to use a temporary array to store the reverse of the array.
●​ Create a temporary array of same size as the original array.

●​ Now, copy all elements from original array to the temporary array

in reverse order.

●​ Finally, copy all the elements from temporary array back to the

original array.

// C Program to reverse an array using temporary array

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

// function to reverse an array


void reverseArray(int arr[], int n) {

// Temporary array to store elements in reversed order


int temp[n];

// Copy elements from original array to temp in reverse order


for(int i = 0; i < n; i++)
temp[i] = arr[n - i - 1];

// Copy elements back to original array


for(int i = 0; i < n; i++)
arr[i] = temp[i];
}

int main() {
int arr[] = { 1, 4, 3, 2, 6, 5 };
int n = sizeof(arr) / sizeof(arr[0]);

reverseArray(arr, n);

for(int i = 0; i < n; i++)


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

return 0;
}

[Expected Approach – 1] Using Two Pointers – O(n) Time and


O(1) Space

The idea is to maintain two pointers: left and right, such that left points at
the beginning of the array and right points to the end of the array.

While left pointer is less than the right pointer, swap the elements at
these two positions. After each swap, increment the left pointer and
decrement the right pointer to move towards the center of array. This will
swap all the elements in the first half with their corresponding element in
the second half.

// C Program to reverse an array using Two Pointers

#include <stdio.h>

// Function to swap two numbers


void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}

// function to reverse an array


void reverseArray(int arr[], int n) {

// Initialize left to the beginning and right to the end


int left = 0, right = n - 1;

// Iterate till left is less than right


while (left < right) {

// Swap the elements at left and right position


swap(&arr[left], &arr[right]);

// Increment the left pointer


left++;

// Decrement the right pointer


right--;
}
}

int main() {
int arr[] = { 1, 4, 3, 2, 6, 5 };
int n = sizeof(arr) / sizeof(arr[0]);

reverseArray(arr, n);

for (int i = 0; i < n; i++)


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

return 0;
}

[Expected Approach – 2] By Swapping Elements – O(n) Time


and O(1) Space

The idea is to iterate over the first half of the array and swap each
element with its corresponding element from the end. So, while iterating
over the first half, any element at index i is swapped with the element at
index (n – i – 1).

// C Program to reverse an array by swapping elements

#include <stdio.h>

// function to reverse an array


void reverseArray(int arr[], int n) {

// Iterate over the first half and for every index i,


// swap arr[i] with arr[n - i - 1]
for (int i = 0; i < n / 2; i++) {
int temp = arr[i];
arr[i] = arr[n - i - 1];
arr[n - i - 1] = temp;
}
}

int main() {
int arr[] = { 1, 4, 3, 2, 6, 5 };
int n = sizeof(arr) / sizeof(arr[0]);

reverseArray(arr, n);

for (int i = 0; i < n; i++)


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

return 0;
}

[Alternate Approach] Using Recursion – O(n) Time and O(n)


Space

The idea is to use recursion and define a recursive function that takes a
range of array elements as input and reverses it. Inside the recursive
function,

●​ Swap the first and last element.

●​ Recursively call the function with the remaining subarray.

// C Program to reverse an array using Recursion

#include <stdio.h>

// recursive function to reverse an array from l to r


void reverseArrayRec(int arr[], int l, int r) {
if(l >= r)
return;

// Swap the elements at the ends


int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;

// Recur for the remaining array


reverseArrayRec(arr, l + 1, r - 1);
}

// function to reverse an array


void reverseArray(int arr[], int n) {
reverseArrayRec(arr, 0, n - 1);
}

int main() {
int arr[] = { 1, 4, 3, 2, 6, 5 };
int n = sizeof(arr) / sizeof(arr[0]);

reverseArray(arr, n);

for(int i = 0; i < n; i++)


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

return 0;
}

Reverse String in C
In C, reversing a string means rearranging the characters such that the last
character becomes the first, the second-to-last character becomes the
second, and so on. In this article, we will learn how to reverse string in C.
The most straightforward method to reverse string is by using two
pointers to swap the corresponding characters starting from beginning
and the end while moving the indexes towards each other till they meet
each other.

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

void rev(char* s) {

// Initialize l and r pointers


int l = 0;
int r = strlen(s) - 1;
char t;

// Swap characters till l and r meet


while (l < r) {

// Swap characters
t = s[l];
s[l] = s[r];
s[r] = t;

// Move pointers towards each other


l++;
r--;
}
}

int main() {
char s[100] = "abcde";

​ // Reversing s
rev(s);

printf("%s", s);
return 0;
}

Using Recursion
The two-pointer approach can also be implemented using recursion. Just
pass the left and the right index pointer as argument to the recursive
function and move them towards each other in each recursive call.

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

void rev(char* s, int l, int r) {

// Base case is when l becomes greater than r


if (l >= r) return;

// Swap characters
char t = s[l];
s[l] = s[r];
s[r] = t;

// Recursively call the function with updated


​ // index pointers
rev(s, l + 1, r - 1);
}

int main() {
char s[100] = "abcde";

rev(s, 0, strlen(s) - 1);


printf("%s", s);
return 0;
}

Using Temporary Array


Store the reverse of string in a temporary array by traversing it from the
back and copying each character to the other array. Then copy the
reversed string from another array into the original string.

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

void rev(char* s) {
char t[100];

int len = strlen(s);


int i = 0;

// Push all characters of string s onto t


while (len > 0) t[i++] = s[len-- - 1];
t[i] = '\0';

// Copying all characters from t to


​ // original string s
strcpy(s, t);
}

int main() {
char s[100] = "abcde";

​ // Reversing string s
rev(s);
printf("%s", s);
return 0;
}

Using Library Function


In C, strrev() defined inside <string.h> can be used to reverse a string. This
function provides the simplest method to reverse the string.

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

int main() {
char s[] = "abcde";

// Reversing string using strrev()


printf("%s", strrev(s));

return 0;
}

# 🧱 Structures and Unions in C – Theory & Examples


---

##🟦 1. **Structures**
### 📘 **Theory:**
A **structure** in C is a **user-defined data type** that allows grouping
variables of **different types** under one name. It is used to create a
complex data type that models real-world entities (like students,
employees, etc.).
### ✅ **Syntax:**
```c
struct StructureName {
data_type member1;
data_type member2;
...
};
```

---

### 🧪 **Example: Basic Structure**


```c
#include <stdio.h>

struct Student {
int roll;
char name[50];
};

int main() {
struct Student s1 = {101, "Punam"};
printf("Roll: %d, Name: %s\n", [Link], [Link]);
return 0;
}
```

---

##🔁 2. **Accessing and Initializing Structures**


### 🧠 **Theory:**
- **Access members:** using dot operator (`[Link]`)
- **Initialize:** either during declaration or later

```c
struct Student s1 = {101, "Punam"};
[Link] = 102;
strcpy([Link], "Aman");
```

---

##🧩 3. **Nested Structures**


### 📘 **Theory:**
A structure defined **inside another structure** is called a **nested
structure**.

### ✅ **Example:**
```c
struct Date {
int day, month, year;
};

struct Student {
int roll;
struct Date dob;
};

int main() {
struct Student s = {1, {10, 12, 2003}};
printf("DOB: %d/%d/%d\n", [Link], [Link], [Link]);
return 0;
}
```

---

##📚 4. **Array of Structures**


### 📘 **Theory:**
You can declare an array of structures to handle multiple records of the
same type.

### ✅ **Example:**
```c
struct Student {
int roll;
char name[50];
};

int main() {
struct Student students[2] = {{1, "Punam"}, {2, "Ankit"}};
for(int i = 0; i < 2; i++) {
printf("%d %s\n", students[i].roll, students[i].name);
}
return 0;
}
```

---

##🧾 5. **Structures and Functions**


### 📘 **Theory:**
Structures can be passed to functions **by value or by reference (using
pointers)**.
### ✅ **Example:**
```c
void display(struct Student s) {
printf("Roll: %d\n", [Link]);
}

void modify(struct Student *s) {


s->roll = 500;
}
```

---

##🔄 6. **Self-Referential Structure**


### 📘 **Theory:**
A structure that contains a **pointer to itself**. Commonly used in **linked
lists** and trees.

### ✅ **Example:**
```c
struct Node {
int data;
struct Node* next;
};
```

---

##🟨 7. **Union**
### 📘 **Theory:**
A **union** is similar to a structure, but all members **share the same
memory**. Only **one member holds a value at a time**.

### ✅ **Syntax:**
```c
union Data {
int i;
float f;
char str[20];
};
```

### ✅ **Example:**
```c
#include <stdio.h>

union Data {
int i;
float f;
};

int main() {
union Data d;
d.i = 10;
printf("%d\n", d.i);

d.f = 5.5;
printf("%f\n", d.f); // d.i is now overwritten
return 0;
}
```

---
## ⚖️ Structure vs Union
| Feature | Structure | Union |
|------------------|----------------------|---------------------|
| Memory allocation| Separate for each | Shared among all |
| Data access | All at the same time | One at a time |
| Use case | Complex data | Memory saving cases |

---

##🏷️ 8. **typedef**
### 📘 **Theory:**
`typedef` creates a **new alias name** for a data type, especially useful
with structs.

### ✅ **Example:**
```c
typedef struct {
int id;
char name[20];
} Student;

int main() {
Student s1 = {1, "Punam"};
printf("%s\n", [Link]);
return 0;
}
```

Now we don’t need to write `struct` again and again.


---

##🔢 9. **Enumerations (enum)**


### 📘 **Theory:**
An `enum` defines a set of **named integer constants**. It improves
**readability** of code, like for `Status`, `Days`, etc.

### ✅ **Example:**
```c
enum Status { OFF, ON, STANDBY };

int main() {
enum Status s = ON;
printf("%d\n", s); // Outputs: 1
return 0;
}
```

### 🔁 You can also assign custom values:


```c
enum Days { MON = 1, TUE = 10, WED = 100 };
```

---

## 🧠 Summary
| Concept | Description |
|------------------------|-----------------------------------------------------
---|
| `struct` | Groups multiple data types |
| Nested Struct | Struct inside another struct |
| Array of Structs | Multiple records (e.g., list of students) |
| Self-Referential Struct| Used in linked list, trees |
| `union` | One-at-a-time memory usage |
| `typedef` | Type alias for cleaner code |
| `enum` | Named constants (e.g., `RED`, `GREEN`, `BLUE`) |

---

Would you like me to compile this into a PDF next, or generate example
code for each one in separate `.c` files?

You might also like