Stack Initialization
Part of the Object Oriented Programming section of Coddy's C journey — lesson 14 of 61.
Not every object needs to live on the heap. When a struct is small and has a short lifespan, allocating it on the stack is simpler and faster—no malloc, no free, no risk of memory leaks.
Instead of returning a pointer, a factory function can return the struct by value. The entire struct gets copied to the caller:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
The caller receives a fully initialized copy:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
No pointers, no cleanup required. When origin and cursor go out of scope, they're automatically destroyed.
This approach works best for small structs without dynamically allocated members. For larger objects or those containing pointers to heap memory, the constructor pattern with malloc remains the better choice.
Challenge
EasyLet's build a Temperature module that creates temperature readings on the stack using a factory function. Unlike the heap-based constructors from previous lessons, this approach returns the struct by value—no malloc, no free, just simple and efficient stack allocation.
You'll create three files:
temperature.h: Declare aTemperaturestruct with two members:double celsiusandchar scale(to store 'C' for Celsius). Also declare two functions:create_temperature— takes a double value and returns aTemperaturestruct by value (not a pointer!)temperature_to_fahrenheit— takes aconst Temperature *and returns the equivalent temperature in Fahrenheit as a double
TEMPERATURE_H.temperature.c: Implement both functions. Your factory function should create a localTemperaturevariable, initialize its fields (setscaleto'C'), and return it. The conversion formula is:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c: Use your factory function to create a temperature reading and display both the Celsius and Fahrenheit values.
You will receive one input: the temperature in Celsius (as a double).
In your main file, use create_temperature to create a Temperature struct with the given value. Then print the original Celsius value and its Fahrenheit equivalent.
Print the output in this format:
Celsius: {celsius}
Fahrenheit: {fahrenheit}Use %.2f for both values to display two decimal places.
For example, with an input of 25.0, the output would be:
Celsius: 25.00
Fahrenheit: 77.00Notice how clean this approach is—you receive a fully initialized struct without any memory management concerns. When your Temperature variable goes out of scope, it's automatically cleaned up.
Cheat sheet
Factory functions can return structs by value instead of pointers. This allocates the struct on the stack—no malloc, no free, and no memory leaks.
Example of a factory function returning by value:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Using the factory function:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
The struct is copied to the caller and automatically destroyed when it goes out of scope. This approach works best for small structs without dynamically allocated members.
Try it yourself
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: Use create_temperature to create a Temperature struct
// TODO: Print the Celsius value using %.2f format
// TODO: Use temperature_to_fahrenheit to convert and print the Fahrenheit value
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