Unit 5 - Notes

CSE101

Unit 5: Pointers, Dynamic memory allocation and Strings

1. Pointers: Declaration and Initialization

Definition

A pointer is a derived data type in C that stores the memory address of another variable. Unlike normal variables that store values (like int a = 10), pointers store the location where that value is held in memory.

Declaration

The general syntax for declaring a pointer involves the dereference operator (*).

C
data_type *pointer_name;

  • data_type: The type of variable the pointer will point to (e.g., int, float, char).
  • *: Indicates that the variable is a pointer.

Initialization

Initialization involves assigning the address of a variable to the pointer using the address-of operator (&).

C
int num = 10;
int *ptr;       // Declaration
ptr = #     // Initialization (ptr now holds the address of num)


2. Types of Pointers

A. Null Pointer

A pointer that is assigned a value of NULL (or 0). It points to nothing. It is good practice to initialize pointers to NULL if they are not assigned a valid address immediately to prevent garbage access.

C
int *ptr = NULL; 

B. Generic (Void) Pointer

A pointer of type void *. It has no associated data type and can hold the address of any type of variable. However, it cannot be dereferenced directly; it must be typecast to a specific type first.

C
int n = 10;
void *ptr = &n;
printf("%d", *(int*)ptr); // Typecasting required

C. Wild Pointer

A pointer that has been declared but not initialized. It points to an arbitrary (random) memory location. Dereferencing a wild pointer can cause the program to crash or behave unexpectedly.

C
int *ptr; // Wild pointer
*ptr = 5; // Dangerous!

D. Dangling Pointer

A pointer that points to a memory location that has already been freed (deallocated) or is out of scope.

C
int *ptr = (int *)malloc(sizeof(int));
free(ptr); 
// ptr is now a dangling pointer because the memory it points to is released.
ptr = NULL; // Fix: Assign NULL after freeing.


3. Pointer Expressions and Arithmetic

Pointers can be used in expressions, but their arithmetic rules differ from standard integer arithmetic. Pointer arithmetic is performed relative to the data type size.

Pointer Operators

  1. & (Address-of Operator): Returns the memory address of a variable.
  2. *`` (Dereference/Indirection Operator):** Accesses the value stored at the address held by the pointer.

Valid Operations on Pointers

  1. Increment (ptr++): Moves the pointer to the next memory location based on the size of the data type.
    • If int *ptr is at address 1000 and sizeof(int) is 4, ptr++ moves to 1004.
  2. Decrement (ptr--): Moves the pointer to the previous memory location.
  3. Addition of Integer (ptr + n): Moves the pointer forward by n * sizeof(type) bytes.
  4. Subtraction of Integer (ptr - n): Moves the pointer backward by n * sizeof(type) bytes.
  5. Subtraction of two pointers (ptr1 - ptr2): Returns the number of elements between the two pointers (provided they point to the same array).

Invalid Operations

  • Addition of two pointers (ptr1 + ptr2).
  • Multiplication or Division of pointers.
  • Bitwise operations on pointers.

4. Passing Pointer to a Function (Call by Reference)

When passing arguments to a function, C uses "Call by Value" by default. To modify the actual arguments in the caller function, we must use pointers (Call by Reference).

Mechanism

  • The address of the variable is passed to the function.
  • The function parameter is a pointer.
  • The function uses the dereference operator (*) to modify the value at that address.

Example: Swapping Two Numbers

C
#include <stdio.h>

void swap(int *x, int *y) {
    int temp = *x; // Get value at address x
    *x = *y;       // Put value at y into address x
    *y = temp;     // Put temp into address y
}

int main() {
    int a = 10, b = 20;
    swap(&a, &b); // Pass addresses
    printf("a = %d, b = %d", a, b); // Output: a = 20, b = 10
    return 0;
}


5. Pointers and One-Dimensional Arrays

In C, the name of an array acts as a constant pointer to the first element of the array.

  • arr is equivalent to &arr[0].
  • Accessing arr[i] is internally converted by the compiler to *(arr + i).

Accessing Array Elements via Pointers

C
int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr; // Points to arr[0]

for(int i = 0; i < 5; i++) {
    // These three print statements output the same value
    printf("%d ", arr[i]);       // Array indexing
    printf("%d ", *(arr + i));   // Pointer arithmetic using array name
    printf("%d ", *(ptr + i));   // Pointer arithmetic using pointer variable
}


6. Dynamic Memory Allocation (DMA)

Static memory allocation (like arrays) reserves memory at compile time. DMA allows allocating memory at runtime using the heap section of memory. These functions are defined in <stdlib.h>.

A. malloc (Memory Allocation)

Allocates a single large block of memory of the specified size.

  • Initialization: Contains garbage values.
  • Return: void* (needs casting). Returns NULL if allocation fails.

C
// Syntax: ptr = (cast_type*) malloc(byte_size);
int *ptr = (int*) malloc(5 * sizeof(int));

B. calloc (Contiguous Allocation)

Allocates multiple blocks of memory of the same size.

  • Initialization: Initializes all bytes to zero.
  • Arguments: Number of blocks, size of each block.

C
// Syntax: ptr = (cast_type*) calloc(n, element_size);
int *ptr = (int*) calloc(5, sizeof(int));

C. realloc (Re-allocation)

Changes the size of the previously allocated memory block (expands or shrinks). It preserves the previous content.

C
// Syntax: ptr = realloc(ptr, new_size);
ptr = realloc(ptr, 10 * sizeof(int));

D. free

Deallocates the memory previously allocated by malloc, calloc, or realloc. This is crucial to prevent memory leaks.

C
// Syntax: free(ptr);
free(ptr);
ptr = NULL; // Good practice


7. Defining and Initializing Strings

A string in C is a one-dimensional array of characters terminated by a null character ('\0').

Declaration and Initialization

  1. Using Character Array:

    C
        char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicit null
        char str[] = "Hello"; // Implicit null (Compiler adds '\0')
        

  2. Using String Pointer:

    C
        char *str = "Hello"; 
        // Note: This creates a string literal in read-only memory. 
        // Usually cannot be modified (e.g., str[0] = 'h' might crash).
        


8. Reading and Writing Strings

Reading Strings

  1. scanf("%s", str);: Reads input until the first whitespace (space, tab, newline). Not suitable for multi-word strings.
  2. gets(str);: Reads a line including spaces. (Warning: unsafe, can cause buffer overflow).
  3. fgets(str, size, stdin);: The safe standard. Reads up to size-1 characters or new line.

Writing Strings

  1. printf("%s", str);: Standard formatted output.
  2. puts(str);: Prints the string followed automatically by a newline.

9. Processing of String and Character Arithmetic

Strings are processed by iterating through the character array until the null terminator (\0) is encountered.

Character Arithmetic

Characters in C are stored as ASCII integer values. We can perform arithmetic on them.

  • 'A' + 1 results in 'B'.
  • '0' is ASCII 48. Converting a char digit to int: int val = char_digit - '0';.
  • Converting Lowercase to Uppercase: char upper = lower - 32; (Since 'a'=97 and 'A'=65).

Example: Manual Length Calculation

C
char str[] = "Program";
int count = 0;
while (str[count] != '\0') {
    count++;
}
printf("Length: %d", count);


10. String Manipulation and Library Functions

The <string.h> library provides built-in functions for string handling.

Common Functions

Function Syntax Description
strlen size_t strlen(const char *str) Returns the length of the string (excluding \0).
strcpy char* strcpy(char *dest, const char *src) Copies content of src to dest.
strcat char* strcat(char *dest, const char *src) Concatenates src to the end of dest.
strcmp int strcmp(const char *s1, const char *s2) Compares two strings character by character (ASCII).
strchr char* strchr(const char *str, int c) Returns pointer to first occurrence of char c in str.

strcmp Return Values

  • 0: Strings are identical.
  • > 0: First non-matching char in s1 has a greater ASCII value than in s2.
  • < 0: First non-matching char in s1 has a lower ASCII value than in s2.

Example Code

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

int main() {
    char s1[20] = "Hello";
    char s2[] = "World";
    char s3[40];

    // Length
    printf("Length of s1: %zu\n", strlen(s1));

    // Copy
    strcpy(s3, s1); // s3 becomes "Hello"
    
    // Concatenate
    strcat(s3, " ");
    strcat(s3, s2); // s3 becomes "Hello World"
    printf("Combined: %s\n", s3);

    // Compare
    if (strcmp(s1, s2) != 0) {
        printf("Strings are different.\n");
    }

    return 0;
}