Deep Copy
Part of the Object Oriented Programming section of Coddy's C journey — lesson 15 of 61.
When you assign one struct to another in C, you get a shallow copy—all fields are copied byte-for-byte. This works fine for simple values like integers, but creates a problem with pointers: both structs end up pointing to the same memory.
typedef struct {
char *name;
int age;
} Person;
Person alice = {"Alice", 30};
Person copy = alice; // Shallow copy!
// Both alice.name and copy.name point to the SAME string
If you free one, the other becomes invalid. If you modify the string through one, both see the change. This is rarely what you want.
A deep copy allocates new memory for pointer members and copies the actual data:
Person *clone_person(const Person *original) {
Person *copy = malloc(sizeof(Person));
copy->name = malloc(strlen(original->name) + 1);
strcpy(copy->name, original->name);
copy->age = original->age;
return copy;
}
Now each object owns its own string. You can modify or free one without affecting the other. The pattern is straightforward: for each pointer member, allocate fresh memory and copy the contents—not just the address.
Challenge
EasyLet's build a Student module that demonstrates the deep copy pattern. You'll create a cloning function that produces a completely independent copy of a student object—one where modifying or freeing the original has no effect on the clone.
You'll create three files:
student.h: Declare aStudentstruct with two members:char *name(a dynamically allocated string) andint grade. Declare three functions:create_student— constructor that takes a name and grade, returns a pointer to a new Studentclone_student— takes aconst Student *and returns a pointer to a new, independent copyfree_student— destructor that properly frees all allocated memory
STUDENT_H.student.c: Implement all three functions. Yourclone_studentfunction is the key—it must allocate fresh memory for both the struct and the name string, then copy the actual string data (not just the pointer address). This ensures the clone owns its own memory completely separate from the original.main.c: Create a student, clone it, display both students' information, then properly clean up both objects.
You will receive two inputs: the student name (a string) and the grade (an integer).
In your main file, create a student with the provided values, then create a clone of that student. Print both the original and the clone's information to verify they contain the same data. Finally, free both students and print a confirmation.
Print the output in this format:
Original: {name}, Grade: {grade}
Clone: {name}, Grade: {grade}
Both freedFor example, with inputs Alice and 95, the output would be:
Original: Alice, Grade: 95
Clone: Alice, Grade: 95
Both freedThe deep copy pattern ensures that each object is truly independent—the clone has its own allocated string, not a shared pointer to the original's memory.
Cheat sheet
When you assign one struct to another in C, you get a shallow copy—all fields are copied byte-for-byte. With pointers, both structs end up pointing to the same memory:
typedef struct {
char *name;
int age;
} Person;
Person alice = {"Alice", 30};
Person copy = alice; // Shallow copy!
// Both alice.name and copy.name point to the SAME string
A deep copy allocates new memory for pointer members and copies the actual data:
Person *clone_person(const Person *original) {
Person *copy = malloc(sizeof(Person));
copy->name = malloc(strlen(original->name) + 1);
strcpy(copy->name, original->name);
copy->age = original->age;
return copy;
}
The deep copy pattern: for each pointer member, allocate fresh memory and copy the contents—not just the address. This ensures each object owns its own memory and can be modified or freed independently.
Try it yourself
#include <stdio.h>
#include <stdlib.h>
#include "student.h"
int main() {
char name[100];
int grade;
// Read input
scanf("%s", name);
scanf("%d", &grade);
// TODO: Create a student with the provided name and grade
// TODO: Create a clone of the student
// TODO: Print the original student's information
// Format: "Original: {name}, Grade: {grade}"
// TODO: Print the clone's information
// Format: "Clone: {name}, Grade: {grade}"
// TODO: Free both students
// Print confirmation
printf("Both freed\n");
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Modular Programming Basics
Header FilesInclude GuardsSource FilesStatic FunctionsRecap: Modular Calculator4Encapsulation
Opaque Pointers ConceptDefining Opaque StructsGetters and SettersValidation in SettersRecap: Secret Box2Objects and Methods
Structs as ObjectsThe 'Self' PointerConst CorrectnessPointer vs ValueHelper MethodsRecap: Point Manager5Project: Simple Bank Account
Project SetupImplementation of Account3Object Lifecycle
Constructor PatternDestructor PatternStack InitializationDeep CopyRecap: String Wrapper6Inheritance via Composition
Struct EmbeddingThe First Member RuleAccessing Parent MembersUpcastingRecap: Shape Hierarchy