c
examples
examples.cš§c
/**
* Pointers to Structures - Examples
*
* This file demonstrates the use of pointers with structures,
* including the arrow operator, dynamic allocation, and linked structures.
*
* Compile: gcc examples.c -o examples
* Run: ./examples
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ============================================================
* EXAMPLE 1: Arrow Operator Basics
* ============================================================ */
struct Person {
char name[50];
int age;
float salary;
};
void example1_arrow_operator(void) {
printf("=== EXAMPLE 1: Arrow Operator Basics ===\n\n");
struct Person person = {"Alice", 30, 75000.0};
struct Person *ptr = &person;
printf("Accessing structure members:\n\n");
// Using dot operator (with structure variable)
printf("Using dot operator (person.member):\n");
printf(" Name: %s\n", person.name);
printf(" Age: %d\n", person.age);
printf(" Salary: %.2f\n\n", person.salary);
// Using arrow operator (with pointer)
printf("Using arrow operator (ptr->member):\n");
printf(" Name: %s\n", ptr->name);
printf(" Age: %d\n", ptr->age);
printf(" Salary: %.2f\n\n", ptr->salary);
// Using dereference + dot (equivalent to arrow)
printf("Using (*ptr).member (equivalent to ptr->member):\n");
printf(" Name: %s\n", (*ptr).name);
printf(" Age: %d\n", (*ptr).age);
printf(" Salary: %.2f\n", (*ptr).salary);
}
/* ============================================================
* EXAMPLE 2: Modifying Structure Through Pointer
* ============================================================ */
void example2_modify_through_pointer(void) {
printf("\n=== EXAMPLE 2: Modifying Through Pointer ===\n\n");
struct Person person = {"Bob", 25, 50000.0};
struct Person *ptr = &person;
printf("Original values:\n");
printf(" Name: %s, Age: %d, Salary: %.2f\n\n",
person.name, person.age, person.salary);
// Modify through pointer
ptr->age = 26;
ptr->salary = 55000.0;
strcpy(ptr->name, "Bobby");
printf("After modification through pointer:\n");
printf(" Name: %s, Age: %d, Salary: %.2f\n",
person.name, person.age, person.salary);
printf("\nNote: Original structure was modified!\n");
}
/* ============================================================
* EXAMPLE 3: Dynamic Structure Allocation
* ============================================================ */
void example3_dynamic_allocation(void) {
printf("\n=== EXAMPLE 3: Dynamic Allocation ===\n\n");
// Allocate single structure
struct Person *person = malloc(sizeof(struct Person));
if (person == NULL) {
printf("Memory allocation failed!\n");
return;
}
// Initialize using arrow operator
strcpy(person->name, "Charlie");
person->age = 35;
person->salary = 80000.0;
printf("Dynamically allocated person:\n");
printf(" Name: %s\n", person->name);
printf(" Age: %d\n", person->age);
printf(" Salary: %.2f\n\n", person->salary);
printf("Structure address: %p\n", (void*)person);
printf("Structure size: %zu bytes\n", sizeof(struct Person));
// Free memory
free(person);
person = NULL; // Good practice
printf("\nMemory freed successfully.\n");
}
/* ============================================================
* EXAMPLE 4: Array of Structures with Pointers
* ============================================================ */
void example4_dynamic_array(void) {
printf("\n=== EXAMPLE 4: Dynamic Array of Structures ===\n\n");
int count = 3;
// Allocate array of structures
struct Person *people = malloc(count * sizeof(struct Person));
if (people == NULL) {
printf("Memory allocation failed!\n");
return;
}
// Initialize using different methods
// Method 1: Array notation
strcpy(people[0].name, "Alice");
people[0].age = 30;
people[0].salary = 70000.0;
// Method 2: Pointer arithmetic with arrow
strcpy((people + 1)->name, "Bob");
(people + 1)->age = 25;
(people + 1)->salary = 55000.0;
// Method 3: Using a pointer variable
struct Person *ptr = &people[2];
strcpy(ptr->name, "Carol");
ptr->age = 40;
ptr->salary = 90000.0;
// Print all
printf("%-10s %-5s %s\n", "Name", "Age", "Salary");
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
for (int i = 0; i < count; i++) {
printf("%-10s %-5d $%.2f\n",
people[i].name, people[i].age, people[i].salary);
}
// Alternative: iterate with pointer
printf("\nUsing pointer iteration:\n");
struct Person *end = people + count;
for (ptr = people; ptr < end; ptr++) {
printf(" %s is %d years old\n", ptr->name, ptr->age);
}
free(people);
}
/* ============================================================
* EXAMPLE 5: Passing Structure by Reference
* ============================================================ */
// Pass by value - doesn't modify original
void incrementAge_ByValue(struct Person p) {
p.age++;
printf(" Inside function (by value): age = %d\n", p.age);
}
// Pass by pointer - modifies original
void incrementAge_ByPointer(struct Person *p) {
p->age++;
printf(" Inside function (by pointer): age = %d\n", p->age);
}
// Pass by const pointer - read only
void printPerson(const struct Person *p) {
printf(" %s, Age: %d, Salary: $%.2f\n",
p->name, p->age, p->salary);
}
void example5_pass_by_reference(void) {
printf("\n=== EXAMPLE 5: Pass by Value vs Reference ===\n\n");
struct Person person = {"David", 30, 60000.0};
printf("Original: age = %d\n\n", person.age);
printf("Passing by value:\n");
incrementAge_ByValue(person);
printf(" After call: age = %d (unchanged)\n\n", person.age);
printf("Passing by pointer:\n");
incrementAge_ByPointer(&person);
printf(" After call: age = %d (modified!)\n\n", person.age);
printf("Using const pointer (read-only):\n");
printPerson(&person);
}
/* ============================================================
* EXAMPLE 6: Returning Structure Pointer from Function
* ============================================================ */
// Factory function - creates and returns pointer
struct Person* createPerson(const char *name, int age, float salary) {
struct Person *p = malloc(sizeof(struct Person));
if (p != NULL) {
strncpy(p->name, name, sizeof(p->name) - 1);
p->name[sizeof(p->name) - 1] = '\0';
p->age = age;
p->salary = salary;
}
return p; // Caller is responsible for freeing
}
// Destructor function
void destroyPerson(struct Person *p) {
if (p != NULL) {
printf(" Destroying: %s\n", p->name);
free(p);
}
}
void example6_factory_function(void) {
printf("\n=== EXAMPLE 6: Factory Pattern ===\n\n");
// Create people using factory function
struct Person *p1 = createPerson("Eve", 28, 65000.0);
struct Person *p2 = createPerson("Frank", 45, 120000.0);
if (p1 == NULL || p2 == NULL) {
printf("Failed to create person!\n");
destroyPerson(p1);
destroyPerson(p2);
return;
}
printf("Created people:\n");
printPerson(p1);
printPerson(p2);
printf("\nCleaning up:\n");
destroyPerson(p1);
destroyPerson(p2);
}
/* ============================================================
* EXAMPLE 7: Linked List with Structure Pointers
* ============================================================ */
struct Node {
int data;
struct Node *next;
};
// Create new node
struct Node* createNode(int data) {
struct Node *node = malloc(sizeof(struct Node));
if (node != NULL) {
node->data = data;
node->next = NULL;
}
return node;
}
// Insert at front
struct Node* insertFront(struct Node *head, int data) {
struct Node *newNode = createNode(data);
if (newNode != NULL) {
newNode->next = head;
}
return newNode;
}
// Print list
void printList(struct Node *head) {
printf(" List: ");
struct Node *current = head;
while (current != NULL) {
printf("%d", current->data);
if (current->next != NULL) {
printf(" -> ");
}
current = current->next;
}
printf(" -> NULL\n");
}
// Count nodes
int countNodes(struct Node *head) {
int count = 0;
struct Node *current = head;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
// Free list
void freeList(struct Node *head) {
struct Node *current = head;
while (current != NULL) {
struct Node *next = current->next;
free(current);
current = next;
}
}
void example7_linked_list(void) {
printf("\n=== EXAMPLE 7: Simple Linked List ===\n\n");
struct Node *head = NULL;
// Build list: 10 -> 20 -> 30 -> NULL
printf("Building list...\n");
head = insertFront(head, 30);
printList(head);
head = insertFront(head, 20);
printList(head);
head = insertFront(head, 10);
printList(head);
printf("\nList has %d nodes\n", countNodes(head));
// Traverse and show addresses
printf("\nTraversing with addresses:\n");
struct Node *current = head;
int index = 0;
while (current != NULL) {
printf(" Node[%d]: data=%d, addr=%p, next=%p\n",
index++, current->data, (void*)current, (void*)current->next);
current = current->next;
}
freeList(head);
printf("\nList freed.\n");
}
/* ============================================================
* EXAMPLE 8: Nested Structures with Pointers
* ============================================================ */
struct Address {
char street[100];
char city[50];
char zip[10];
};
struct Employee {
char name[50];
int id;
struct Address *address; // Pointer to nested structure
};
void example8_nested_pointers(void) {
printf("\n=== EXAMPLE 8: Nested Structure Pointers ===\n\n");
// Allocate employee and address separately
struct Employee *emp = malloc(sizeof(struct Employee));
struct Address *addr = malloc(sizeof(struct Address));
if (emp == NULL || addr == NULL) {
printf("Memory allocation failed!\n");
free(emp);
free(addr);
return;
}
// Initialize address
strcpy(addr->street, "123 Main Street");
strcpy(addr->city, "New York");
strcpy(addr->zip, "10001");
// Initialize employee with address pointer
strcpy(emp->name, "Grace Hopper");
emp->id = 1001;
emp->address = addr;
// Access nested data through pointers
printf("Employee Information:\n");
printf(" Name: %s\n", emp->name);
printf(" ID: %d\n", emp->id);
printf(" Street: %s\n", emp->address->street);
printf(" City: %s\n", emp->address->city);
printf(" ZIP: %s\n", emp->address->zip);
// Clean up (free nested first)
free(emp->address);
free(emp);
printf("\nMemory freed (nested first, then parent).\n");
}
/* ============================================================
* EXAMPLE 9: Function Pointers in Structures
* ============================================================ */
typedef struct {
int value;
void (*increment)(void *self);
void (*decrement)(void *self);
void (*print)(const void *self);
} Counter;
void counter_increment(void *self) {
Counter *c = (Counter*)self;
c->value++;
}
void counter_decrement(void *self) {
Counter *c = (Counter*)self;
c->value--;
}
void counter_print(const void *self) {
const Counter *c = (const Counter*)self;
printf(" Counter value: %d\n", c->value);
}
void initCounter(Counter *c, int initial) {
c->value = initial;
c->increment = counter_increment;
c->decrement = counter_decrement;
c->print = counter_print;
}
void example9_function_pointers(void) {
printf("\n=== EXAMPLE 9: Simulating OOP with Function Pointers ===\n\n");
Counter counter;
initCounter(&counter, 10);
printf("Initial:\n");
counter.print(&counter);
printf("\nAfter 3 increments:\n");
counter.increment(&counter);
counter.increment(&counter);
counter.increment(&counter);
counter.print(&counter);
printf("\nAfter 1 decrement:\n");
counter.decrement(&counter);
counter.print(&counter);
}
/* ============================================================
* EXAMPLE 10: Doubly Linked List
* ============================================================ */
struct DLLNode {
int data;
struct DLLNode *prev;
struct DLLNode *next;
};
struct DLLNode* createDLLNode(int data) {
struct DLLNode *node = malloc(sizeof(struct DLLNode));
if (node != NULL) {
node->data = data;
node->prev = NULL;
node->next = NULL;
}
return node;
}
void insertDLLBack(struct DLLNode **head, struct DLLNode **tail, int data) {
struct DLLNode *newNode = createDLLNode(data);
if (newNode == NULL) return;
if (*head == NULL) {
*head = *tail = newNode;
} else {
(*tail)->next = newNode;
newNode->prev = *tail;
*tail = newNode;
}
}
void printDLLForward(struct DLLNode *head) {
printf(" Forward: NULL <-> ");
while (head != NULL) {
printf("%d <-> ", head->data);
head = head->next;
}
printf("NULL\n");
}
void printDLLBackward(struct DLLNode *tail) {
printf(" Backward: NULL <-> ");
while (tail != NULL) {
printf("%d <-> ", tail->data);
tail = tail->prev;
}
printf("NULL\n");
}
void freeDLL(struct DLLNode *head) {
while (head != NULL) {
struct DLLNode *next = head->next;
free(head);
head = next;
}
}
void example10_doubly_linked(void) {
printf("\n=== EXAMPLE 10: Doubly Linked List ===\n\n");
struct DLLNode *head = NULL;
struct DLLNode *tail = NULL;
// Insert elements
insertDLLBack(&head, &tail, 10);
insertDLLBack(&head, &tail, 20);
insertDLLBack(&head, &tail, 30);
insertDLLBack(&head, &tail, 40);
printf("Doubly Linked List traversal:\n");
printDLLForward(head);
printDLLBackward(tail);
freeDLL(head);
}
/* ============================================================
* MAIN FUNCTION
* ============================================================ */
int main() {
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("ā POINTERS TO STRUCTURES - EXAMPLES ā\n");
printf("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n\n");
example1_arrow_operator();
example2_modify_through_pointer();
example3_dynamic_allocation();
example4_dynamic_array();
example5_pass_by_reference();
example6_factory_function();
example7_linked_list();
example8_nested_pointers();
example9_function_pointers();
example10_doubly_linked();
printf("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
printf("All examples completed successfully!\n");
return 0;
}