Unit 5 - Notes
CSE109
Unit 5: Dynamic Memory Management and Strings
Part 1: Dynamic Memory Management
In C programming, memory allocation can be static (compile-time) or dynamic (run-time). Dynamic Memory Management (DMM) allows programs to obtain memory from the heap segment during execution, enabling flexible data structures (like linked lists) and arrays where the size is not known until the program runs.
To use DMM functions, the <stdlib.h> header file must be included.
1. The malloc() Function
Name: Memory Allocation
Description: Allocates a single block of requested memory.
Initialization: It does not clear or initialize the memory. The block contains garbage values.
Syntax:
void* malloc(size_t size);
- Parameter:
sizein bytes. - Return: A
voidpointer to the first byte of the allocated memory, orNULLif allocation fails.
Example:
int *ptr;
int n = 5;
// Allocate memory for 5 integers
ptr = (int*) malloc(n * sizeof(int));
if (ptr == NULL) {
printf("Memory not allocated.\n");
exit(0);
}
2. The calloc() Function
Name: Contiguous Allocation
Description: Allocates multiple blocks of memory. It is primarily used for arrays.
Initialization: It initializes all bytes to zero.
Syntax:
void* calloc(size_t n, size_t element_size);
- Parameters:
n(number of elements),element_size(size of each element). - Return: A
voidpointer to the allocated memory, orNULLif failure.
Difference between malloc and calloc: |
Feature | malloc |
calloc |
|---|---|---|---|
| Arguments | 1 (total size) | 2 (count, size of one) | |
| Initialization | Garbage values | Zero initialized | |
| Speed | Slightly faster | Slightly slower (due to zeroing) |
3. The realloc() Function
Name: Re-Allocation
Description: Modifies the size of a previously allocated memory block. It can expand or shrink the memory.
Syntax:
void* realloc(void *ptr, size_t new_size);
- Parameters:
ptr(pointer to existing memory),new_size(new total size in bytes). - Behavior:
- If
new_size> old size: Expands memory. Existing data is preserved. New space is uninitialized. If it cannot expand in place, it moves the data to a new location and frees the old one. - If
new_size< old size: Truncates the memory (data at the end is lost).
- If
Example:
// Increasing the size from 5 integers to 10
ptr = (int*) realloc(ptr, 10 * sizeof(int));
4. The free() Function
Name: Free Memory
Description: Deallocates memory previously allocated by malloc, calloc, or realloc.
Importance: Since heap memory is not automatically cleaned up when a function returns, explicit freeing is required to return memory to the system.
Syntax:
void free(void *ptr);
Dangling Pointer: After calling free(ptr), ptr still holds the address of the memory location, but that memory is no longer valid. Using ptr again causes undefined behavior. It is good practice to set ptr = NULL after freeing.
5. Memory Leak
Definition: A memory leak occurs when programmers create a memory in the heap and forget to delete it. The memory is no longer needed by the program but is not returned to the operating system.
Consequences:
- Reduced available system memory.
- Performance degradation (thrashing).
- Program crash (Out of Memory) if the process runs for a long time (e.g., servers).
Example of a Leak:
void function() {
int *p = (int*) malloc(sizeof(int)); // Allocation
*p = 10;
// Function ends, 'p' (stack variable) is destroyed.
// The heap memory allocated remains occupied but is now unreachable.
}
Part 2: Strings in C
In C, there is no intrinsic "string" data type (like String in Java or Python). A string is defined as a one-dimensional array of characters terminated by a special character called the null character ('\0').
1. Defining and Initializing Strings
A. Array Syntax
When defining a string as a character array, you must ensure there is space for the characters plus the null terminator.
// Method 1: Sizing automatically
char str1[] = "Hello";
// Size is 6 bytes ('H','e','l','l','o','\0')
// Method 2: Sizing explicitly
char str2[10] = "World";
// Size is 10 bytes. First 6 are filled, rest are usually zeroed.
// Method 3: Character by character
char str3[] = {'C', 'o', 'd', 'e', '\0'};
// EXPLICIT null terminator required here.
B. Pointer Syntax
Strings can be defined as a pointer to a string constant.
char *ptr = "Programming";
- Note: String literals defined this way are often stored in read-only memory. Trying to modify them (e.g.,
ptr[0] = 'X';) may cause a Segmentation Fault.
2. Reading and Writing Strings
Writing (Output)
printf: Uses the%sformat specifier.
Cprintf("%s", str);puts: Prints the string and automatically adds a newline character\n.
Cputs(str);
Reading (Input)
scanf: Reads a string but stops at whitespace (space, tab, newline).
Cchar name[20]; scanf("%s", name); // Input: "John Doe" -> Stores: "John"gets(Deprecated): Reads a line including spaces. Unsafe because it does not check buffer size (causes buffer overflow).fgets(Recommended): Reads a line safely by specifying the maximum size.
Cchar buffer[100]; // Syntax: fgets(array, max_size, input_stream) fgets(buffer, 100, stdin);
3. Processing of String
String processing involves iterating through the character array until the null terminator (\0) is encountered.
Generic Logic:
int i = 0;
while (str[i] != '\0') {
// Process str[i]
i++;
}
4. Character Arithmetic
Characters in C are stored as integer ASCII values. This allows for arithmetic operations on characters.
- ASCII Ranges:
- 'A' - 'Z': 65 - 90
- 'a' - 'z': 97 - 122
- '0' - '9': 48 - 57
Common Operations:
- Convert Lowercase to Uppercase: Subtract 32.
Cchar lower = 'c'; // ASCII 99 char upper = lower - 32; // 99 - 32 = 67 ('C') - Convert Char Digit to Int: Subtract '0'.
Cchar c = '5'; int num = c - '0'; // 53 - 48 = 5 - Check position:
C// Alphabetical distance int dist = 'E' - 'A'; // Returns 4
5. String Manipulation and Library Functions
The C Standard Library provides the <string.h> header for string operations.
A. strlen (String Length)
Calculates the length of the string excluding the null terminator.
size_t strlen(const char *str);
// Example
char s[] = "Hi";
int len = strlen(s); // Returns 2
B. strcpy (String Copy)
Copies the content of the source string to the destination string.
- Warning: Destination must be large enough to hold the source.
Cchar *strcpy(char *dest, const char *src); // Example char src[] = "Source"; char dest[20]; strcpy(dest, src); // dest becomes "Source"
C. strcat (String Concatenation)
Appends the source string to the end of the destination string.
char *strcat(char *dest, const char *src);
// Example
char s1[20] = "Hello ";
char s2[] = "World";
strcat(s1, s2); // s1 becomes "Hello World"
D. strcmp (String Compare)
Compares two strings lexicographically (based on ASCII values).
int strcmp(const char *str1, const char *str2);
Return Values:
- 0: Strings are identical.
- < 0:
str1is less thanstr2(e.g., "Apple" vs "Banana"). - > 0:
str1is greater thanstr2(e.g., "Zebra" vs "Apple").
E. strrev (String Reverse)
Note: strrev is a non-standard function (specific to some compilers like Turbo C). In standard GCC/Clang, you must write your own loop to reverse a string.
Manual Reverse Logic:
void reverse(char *str) {
int i = 0, j = strlen(str) - 1;
while (i < j) {
char temp = str[i];
str[i] = str[j];
str[j] = temp;
i++; j--;
}
}
6. Character Handling Functions (<ctype.h>)
While processing strings, helper functions in <ctype.h> are often used to test or manipulate individual characters.
isalpha(c): Checks ifcis a letter.isdigit(c): Checks ifcis a number (0-9).isspace(c): Checks for whitespace.toupper(c): Convertscto uppercase.tolower(c): Convertscto lowercase.