0% found this document useful (0 votes)
2 views

Dynamic Memory Allocation

The document explains dynamic and static memory allocation, highlighting functions like malloc, calloc, realloc, and free for managing memory in C. It also covers linked lists, detailing their structure, traversal, insertion, and deletion operations. Key differences between malloc and calloc, as well as the use of memset, are discussed, emphasizing the importance of proper memory management to avoid leaks and errors.

Uploaded by

Vedant Vakharia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Dynamic Memory Allocation

The document explains dynamic and static memory allocation, highlighting functions like malloc, calloc, realloc, and free for managing memory in C. It also covers linked lists, detailing their structure, traversal, insertion, and deletion operations. Key differences between malloc and calloc, as well as the use of memset, are discussed, emphasizing the importance of proper memory management to avoid leaks and errors.

Uploaded by

Vedant Vakharia
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Dynamic Memory Allocation

Static memory
Static Memory stores temporary variables created by a function. In stack, variables are
declared, stored, and initialized during runtime. It follows the First in last out method, that
means whatever element is going to store last is going to delete first when it’s not in use. Size is
fixed at compile-time.

Heap/Dynamic Memory
Size is decided at runtime (while your program is running). More flexible and efficient.

1. malloc(memory allocation) - Allocates a block of memory of given size but doesn’t


initialize it (contains garbage).

1 ptr = (data_type *) malloc(size_in_bytes);

2. calloc(contiguous allocation) - it initializes the allocated memory to zero

1 ptr = (data_type *) calloc(num_elements, size_of_each);

3. realloc() - realloc() function is used to resize a previously allocated memory block. It allows
you to change the size of an existing memory allocation without needing to free the old
memory and allocate a new block.

1 ptr = (data_type *) realloc(ptr, new size);


2
3 int *ptr = (int *)malloc(5 * sizeof(int));
4 ptr = (int *)realloc(ptr, 10 * sizeof(int));

4. free() - The memory allocated using functions malloc() and calloc() is not de-allocated on
their own. The free() function is used to release dynamically allocated memory back to the
operating system. It is essential to free memory that is no longer needed to avoid memory
leaks.
5. memset() - Fills a block of memory with a specified byte value. memset works byte-by-
byte and not element wise. It is included in string.h .

1 void *memset(void *ptr, int value, size_t num);


2 \\ ptr - Pointer to the starting memory block
3 \\ value - Value to set (in bytes, only the lower 8 bits are used)
4 \\ num - Number of **bytes** to set

1. Uses of memset() -
1. Used with malloc - malloc + memset gives the same effect of calloc when
memset initializes each element to 0.
2. Used with strings and arrays - It can initialize the whole array or string to the
character or integer.
2. Problems with memset() -
1. Initializing to int - As memset() works bitwise and not element wise, it creates
errors when we try to initialize it to numbers as OS works on hex.
So for example if we try to this,
memset(arr, 5, sizeof(arr));
memset fills every byte of the memory block with the value 5 i.e., 0x05 in hex.
Byte-wise memory becomes -
[0x05, 0x05, 0x05, 0x05, | 0x05, 0x05, 0x05, 0x05, | ... 20 times
total]
Now, when the computer reads the first 4 bytes (as an int ), it sees:
[0x05, 0x05, 0x05, 0x05] = 0x05050505 = 84215045
Since an int in C is usually 4 bytes, each int in memory becomes 0x05050505
which equals 84215045. So instead of an array initialized to 5, we get
[84215045, 84215045, 84215045, 84215045, 84215045]
So, for integers, we need to use a for loop and manually set each element to the
integer.
Now it works for 0 and -1(sort of)
It works for 0 as hex of 0 is also 0.
When we pass -1, it is passed as an int , but only the lower 8 bits are
used. So -1 becomes 0xFF (i.e., 255 in unsigned byte form). Each byte
becomes 0xFF . This results in
int = [0xFF, 0xFF, 0xFF, 0xFF] = 0xFFFFFFFF
Which is in two's complement, 0xFFFFFFFF = -1 for a 32-bit int .
So, it works !!
2.
3.

6. Malloc vs Calloc -
c - Why malloc+memset is slower than calloc? - Stack Overflow
Why does calloc exist? — njs blog
c - Difference between malloc and calloc? - Stack Overflow
c - calloc v/s malloc and time efficiency - Stack Overflow

Linked Lists
A Linked List is a linear data structure where each element (node) contains the data (value) and
a pointer to the next node. Unlike arrays, linked lists don’t store elements in contiguous memory
— they’re dynamically allocated.

The address of the first node a special name called HEAD. Also, the last node in the linked list
can be identified because its next portion points to NULL.

General Syntax -

1 struct Node {
2 int data;
3 struct Node* next;
4 };

Single Linked Lists -

1. Traverse a Linked List - We keep moving the temp node to the next one and display its
contents. When temp is NULL, we know that we have reached the end of the linked list so
we get out of the while loop.

1 struct node *temp = head;


2 printf("\n\nList elements are - \n");
3 while(temp != NULL) {
4 printf("%d --->",temp->data);
5 temp = temp->next;
6 }

2. Insert Elements to a Linked List -


1. Insert after the i node -

1 //We create a temporary pointer `temp` to walk through the list starting
from the head.
2 void insertAfterPosition(struct Node* head, int i, int new_data) {
3
4 struct Node* temp = head;
5
6 // Traverse to the i-th node
7 for (int pos = 0; pos < i; pos++) {
8 emp = temp->next;}
9
10
11 // Allocate new node
12 struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
13 new_node->data = new_data;
14
15 // Insert after the i-th node
16 new_node->next = temp->next;
17 temp->next = new_node;
18 }

2. Insert at beginning -
Allocate memory for new node
Store data
Change next of new node to point to head
Change head to point to recently created node

1 struct node *newNode;


2 newNode = malloc(sizeof(struct node));
3 newNode->data = 4;
4 newNode->next = head;
5 head = newNode;

3. Insert at end -

1 struct node *newNode;


2 newNode = malloc(sizeof(struct node));
3 newNode->data = 4;
4 newNode->next = NULL;
5
6 struct node *temp = head;
7 while(temp->next != NULL){
8 temp = temp->next;
9 }
10
11 temp->next = newNode;

3. Delete nodes from a linked list -


1. Delete the ith node -

1 void deleteAtPosition(struct Node** head_ref, int i) {


2
3 struct Node* temp = *head_ref;
4
5 // Traverse to the (i-1)th node
6 for (int pos = 0; pos < i - 1; pos++) {
7 if (temp == NULL || temp->next == NULL) {
8 printf("Position %d is out of bounds.\n", i);
9 return;
10 }
11 temp = temp->next;
12 }
13
14 // temp points to (i-1)th node now
15 struct Node* nodeToDelete = temp->next;
16
17 temp->next = nodeToDelete->next; // Skip the i-th node
18 free(nodeToDelete); // Free memory
19 }

2. Delete the 1st node - Point head to the second node

1 head = head->next;

3. Delete the last node -


Traverse to second last element
Change its next pointer to null

1 struct node* temp = head;


2 while(temp->next->next!=NULL){
3 temp = temp->next;
4 }
5 temp->next = NULL;

4.

You might also like