Menu
Coddy logo textTech

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 icon

Challenge

Easy

Let'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 a Temperature struct with two members: double celsius and char scale (to store 'C' for Celsius). Also declare two functions:
    • create_temperature — takes a double value and returns a Temperature struct by value (not a pointer!)
    • temperature_to_fahrenheit — takes a const Temperature * and returns the equivalent temperature in Fahrenheit as a double
    Use include guards with the symbol TEMPERATURE_H.
  • temperature.c: Implement both functions. Your factory function should create a local Temperature variable, initialize its fields (set scale to 'C'), and return it. The conversion formula is: fahrenheit = celsius * 9.0 / 5.0 + 32.0
  • main.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.00

Notice 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;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming