====== Lab 08 - Selected topics from previous lectures ====== ==== Task 0 (DIY): Pointer fundamentals ==== Compile and run the following program. Observe its output and think carefully about why the addresses and values appear as they do. #include int main(void) { int arr[5] = {10, 20, 30, 40, 50}; int *p = arr; printf("Array variable (arr): %p\n", (void*)arr); printf("Address of first element: %p\n", (void*)&arr[0]); printf("Pointer variable (p): %p\n", (void*)p); printf("Address of pointer variable: %p\n", (void*)&p); printf("\n--- Elements and addresses ---\n"); for (int i = 0; i < 5; i++) { printf("arr[%d] = %d, address = %p\n", i, arr[i], (void*)&arr[i]); } printf("\n--- Pointer arithmetic ---\n"); for (int i = 0; i < 5; i++) { printf("*(p + %d) = %d, address = %p\n", i, *(p + i), (void*)(p + i)); } return 0; } ---- ==== Task 1: Swapping Two Integers ==== Complete the program below so that it swaps the values of two integers using pointers. Compile, run, and verify that the values are actually swapped. #include void swap(??? a, ??? b); int main(void) { int x = 10; int y = 20; printf("Before swap: x = %d, y = %d\n", x, y); // Call the swap function swap(??? , ???); printf("After swap: x = %d, y = %d\n", x, y); return 0; } // Implement this function void swap(??? a, ??? b) { // Your code here } ---- ==== Task 2: Linked List and Dynamic Allocation ==== In this lab, you will explore linked lists, pointers, stack vs heap allocation, and basic dynamic memory management. #include #include // Node structure typedef struct Node { int value; struct Node *next; } Node; void traverse(Node *head); // Step 1: Create three stack-allocated nodes Node* create_list_stack(void) { Node n1 = {10, NULL}; Node n2 = {20, NULL}; Node n3 = {30, NULL}; n1.next = &n2; // n1 is head n2.next = &n3; n3.next = NULL; // TODO: Call traverse function to print list // traverse(???); return &n1; // returning pointer to stack-allocated node (unsafe!) } // Step 2: Traverse function prototype void traverse(Node *head) { // TODO: Implement traversal using a pointer } // Step 3: Create three heap-allocated nodes Node* create_list_heap(void) { // TODO: Use malloc to create three nodes //Node *n1 = ???; //Node *n2 = ???; //Node *n3 = ???; // TODO: Assign values and link nodes // TODO: Return head of the list return NULL; } // Step 4: Insert a new node after a node with given value void insert_node(Node *head, int value, int after_value) { // TODO: Allocate new node using malloc //Node *new_node = ???; // TODO: Find node with after_value //Node *current = ???; // TODO: Insert new_node after current node //???; } // Step 5: Delete a node by value void delete_node(Node **head_ref, int value) { // TODO: Find node to delete //Node *current = ???; //Node *prev = ???; // TODO: Update pointers to remove node from list //???; // TODO: Free deleted node //???; } // Step 6: Main function to test everything int main(void) { // Step 1: Test stack-based list Node *head_stack = create_list_stack(); // TODO: Call traverse and observe failure // traverse(head_stack); // Step 2: Test heap-based list //Node *head = create_list_heap(); //traverse(head); // Step 3: Insert a new node (value 15 after 10) //insert_node(head, 15, 10); //traverse(head); // Step 4: Delete node with value 20 //delete_node(&head, 20); //traverse(head); // Step 5: Free remaining nodes // free all heap-allocated nodes return 0; } - **Traversal** * Implement a function void traverse(Node *head) that traverses the linked list and prints all node values using a pointer. - **Heap Allocation** * Implement a function Node * create_list_heap() that creates three nodes on the heap using ''malloc''. * Link the nodes and return a pointer to the head. * Call ''traverse()'' to verify the list prints correctly. - **Insertion** * Implement a function void insert_node(Node *head, int value, int after_value) that inserts a new node after a node with the given value. * Test insertion by adding a node with value ''15'' after the node with value ''10''. * Call ''traverse()'' to verify the list. - **Deletion** * Implement a function void delete_node(Node **head_ref, int value) that deletes a node with the given value. * Pass a pointer to the head pointer to handle deleting the first node if needed. * Test deletion by removing the node with value ''20''. * Call ''traverse()'' to verify the list. - **Testing** * Call all functions from ''main()'' and observe that the linked list operations work as expected. * Free all heap-allocated memory when done.