Structs as Objects
Part of the Object Oriented Programming section of Coddy's C journey — lesson 6 of 61.
In object-oriented languages, an object is an entity that bundles data (state) with functions that operate on that data (methods). C doesn't have built-in objects, but we can achieve the same concept using structs and functions.
Think of a struct as the "data" part of an object. It holds the state—the values that define what the object currently is:
typedef struct {
int value;
} Counter;
This Counter struct represents an entity with a single piece of state: its current value. To give it behavior, we write functions that accept the struct as a parameter:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
These functions act like methods—they operate specifically on Counter data. By passing the struct to functions, we're simulating what other languages do automatically when you call counter.increment().
int main() {
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // Prints: 1
return 0;
}
The naming convention typename_action (like counter_increment) helps organize your code and makes it clear which struct a function belongs to. This pattern is the foundation of object-oriented programming in C.
Challenge
EasyLet's build a simple Counter module that treats a struct as an object with behavior. You'll organize your code across three files to practice the pattern of bundling data with functions that operate on it.
You'll create three files:
counter.h: Your header file declaring theCounterstruct with a singleint valuemember. Also declare two functions that act as "methods" for the counter:counter_increment(takes a pointer to Counter and increases its value by 1) andcounter_get(takes a pointer to Counter and returns its current value). Use include guards with the symbolCOUNTER_H.counter.c: Your source file implementing both functions. Remember to include your header file.main.c: Your main file that creates a Counter, performs operations on it, and displays the results.
You will receive two integer inputs: the starting value for your counter and the number of times to increment it.
In your main file, initialize a Counter with the starting value, then call counter_increment the specified number of times. Finally, use counter_get to retrieve and print the final value.
Print the result in this format:
Final value: {result}For example, with a starting value of 5 and 3 increments, the output would be:
Final value: 8Cheat sheet
In C, we can simulate object-oriented programming by combining structs (data) with functions (behavior) that operate on those structs.
Define a struct to hold the state:
typedef struct {
int value;
} Counter;
Create functions that act as "methods" by accepting the struct as a parameter:
void counter_increment(Counter *c) {
c->value++;
}
int counter_get(Counter *c) {
return c->value;
}
Use the struct and functions together:
Counter my_counter = {0};
counter_increment(&my_counter);
printf("%d\n", counter_get(&my_counter)); // Prints: 1
The naming convention typename_action (e.g., counter_increment) helps organize code and clarifies which struct a function operates on.
Try it yourself
#include <stdio.h>
#include "counter.h"
int main() {
// Read input
int starting_value;
int num_increments;
scanf("%d", &starting_value);
scanf("%d", &num_increments);
// TODO: Create a Counter and initialize it with starting_value
// TODO: Call counter_increment the specified number of times
// TODO: Use counter_get to retrieve the final value and print it
// Print format: "Final value: {result}"
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