Inicialización en Stack
Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 14 de 61.
No todos los objetos necesitan residir en el heap. Cuando un struct es pequeño y tiene un tiempo de vida corto, asignarlo en el stack es más sencillo y rápido: sin malloc, sin free y sin riesgo de fugas de memoria.
En lugar de devolver un puntero, una función de fábrica puede devolver el struct por valor. El struct completo se copia al llamador:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
El llamador recibe una copia completamente inicializada:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
Sin punteros, no se requiere limpieza. Cuando origin y cursor salen de ámbito, se destruyen automáticamente.
Este enfoque funciona mejor para structs pequeñas sin miembros asignados dinámicamente. Para objetos más grandes o aquellos que contienen punteros a la memoria heap, el patrón de constructor con malloc sigue siendo la mejor opción.
Desafío
FácilVamos a construir un módulo Temperature que crea lecturas de temperatura en el stack utilizando una función de fábrica (factory function). A diferencia de los constructores basados en el heap de lecciones anteriores, este enfoque devuelve la estructura por valor: sin malloc, sin free, solo una asignación en el stack simple y eficiente.
Crearás tres archivos:
temperature.h: Declara una estructuraTemperaturecon dos miembros:double celsiusychar scale(para almacenar'C'para Celsius). También declara dos funciones:create_temperature— toma un valor double y devuelve una estructuraTemperaturepor valor (¡no un puntero!)temperature_to_fahrenheit— toma unconst Temperature *y devuelve la temperatura equivalente en Fahrenheit como un double
TEMPERATURE_H.temperature.c: Implementa ambas funciones. Tu función de fábrica debe crear una variable localTemperature, inicializar sus campos (establecescalea'C') y devolverla. La fórmula de conversión es:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c: Usa tu función de fábrica para crear una lectura de temperatura y mostrar tanto el valor en Celsius como en Fahrenheit.
Recibirás una entrada: la temperatura en Celsius (como un double).
En tu archivo principal, usa create_temperature para crear una estructura Temperature con el valor dado. Luego imprime el valor original en Celsius y su equivalente en Fahrenheit.
Imprime la salida en este formato:
Celsius: {celsius}
Fahrenheit: {fahrenheit}Usa %.2f para ambos valores para mostrar dos decimales.
Por ejemplo, con una entrada de 25.0, la salida sería:
Celsius: 25.00
Fahrenheit: 77.00Observa lo limpio que es este enfoque: recibes una estructura completamente inicializada sin preocupaciones de gestión de memoria. Cuando tu variable Temperature sale de su ámbito (scope), se limpia automáticamente.
Pruébalo tú mismo
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: Usa create_temperature para crear una struct Temperature
// TODO: Imprime el valor Celsius usando el formato %.2f
// TODO: Usa temperature_to_fahrenheit para convertir e imprimir el valor Fahrenheit
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Fundamentos de programación modular
Archivos de cabeceraGuardas de inclusiónArchivos fuenteFunciones estáticasRepaso: Calculadora modular4Encapsulamiento
Concepto de punteros opacosDefinición de structs opacosGetters y SettersValidación en settersResumen: Caja secreta7Punteros a funciones
Declaración de punteros a funcionesLlamada a punteros a funcionesTypedef para punteros a funcionesPasar funciones como argumentosRepaso: Dispatch de calculadora10Contenedores genéricos
Repaso de punteros voidWrapper genéricoSwap genéricoComparación genéricaRepaso: Array genérico2Objetos y métodos
Structs como objetosEl puntero 'Self'Const CorrectnessPuntero vs. ValorMétodos auxiliaresResumen: Point Manager5Proyecto: Cuenta bancaria simple
Configuración del proyectoImplementación de la cuenta3Ciclo de vida de los objetos
Patrón ConstructorPatrón DestructorInicialización en StackCopia profundaResumen: String Wrapper6Herencia mediante composición
Incrustación de StructsLa regla del primer miembroAcceso a miembros padreUpcastingResumen: Jerarquía de formas9Proyecto: Dibujador de figuras
Descripción general del proyectoImplementación del círculoImplementación del rectánguloUso polimórficoContenedor de figuras