Menu
Coddy logo textTech

Puntero vs. Valor

Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 9 de 61.

Cuando pasas una estructura a una función, C te ofrece dos opciones: pasarla por valor (copiar la estructura completa) o pasarla por puntero (copiar solo la dirección). La elección es muy importante para el rendimiento.

Pasar por valor crea una copia completa del struct en la pila (stack). Para un struct pequeño con unos pocos enteros, esto está bien. Pero imagina un struct con cientos de bytes: cada llamada a función copia todos esos datos:

typedef struct {
    char name[100];
    int scores[50];
    double average;
} Student;

// Por valor: copia ~608 bytes en cada llamada
void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);
}

// Por puntero: copia solo 8 bytes (la dirección)
void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);
}

La sintaxis también difiere. Con un parámetro de valor, se utiliza el operador de punto (s.name). Con un puntero, se utiliza el operador de flecha (s->name).

La versión de puntero es más eficiente porque solo pasa una dirección de memoria; normalmente 8 bytes, independientemente del tamaño de la struct.

Esta es la razón por la que los programadores de C casi siempre pasan estructuras por puntero. Usa const cuando la función no deba modificar los datos, y un puntero regular cuando deba hacerlo. Obtienes tanto eficiencia como una intención clara.

challenge icon

Desafío

Fácil

Vamos a construir un módulo Product que demuestre la diferencia entre pasar estructuras por valor y por puntero. Crearás dos funciones de visualización: una que recibe la estructura completa como una copia y otra que recibe solo un puntero a ella.

Crearás tres archivos:

  • product.h: Declara una estructura Product con tres miembros: char name[50], double price e int quantity. También declara dos funciones:
    • display_by_value — toma un Product por valor e imprime su información
    • display_by_pointer — toma un const Product * e imprime la misma información
    Usa protectores de inclusión (include guards) con el símbolo PRODUCT_H.
  • product.c: Implementa ambas funciones. Observa la diferencia de sintaxis: la versión por valor utiliza el operador punto (p.name), mientras que la versión por puntero utiliza el operador flecha (p->name). Ambas funciones deben imprimir en el mismo formato.
  • main.c: Crea un Product, luego llama a ambas funciones de visualización para mostrar que producen una salida idéntica a pesar de usar diferentes estilos de parámetros.

Recibirás tres entradas: el product name (una cadena), el price (un double) y la quantity (un entero).

En tu archivo principal, inicializa un Product con estos valores, luego llama a display_by_value seguido de display_by_pointer.

Ambas funciones deben imprimir en este formato:

Product: {name}, Price: {price}, Qty: {quantity}

Usa %.2f para el precio para mostrar dos decimales.

Por ejemplo, con las entradas Laptop, 999.99 y 5, la salida sería:

Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5

Hoja de referencia

Al pasar structs a funciones, puedes elegir entre pasar por valor (copiar el struct completo) o pasar por puntero (copiar solo la dirección).

Pasar por valor crea una copia completa del struct:

void print_by_value(Student s) {
    printf("%s: %.2f\n", s.name, s.average);  // Use dot operator
}

Pasar por puntero pasa solo la dirección de memoria:

void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);  // Use arrow operator
}

Diferencias clave:

  • Por valor utiliza el operador punto (s.member)
  • Por puntero utiliza el operador flecha (s->member)
  • Los punteros son más eficientes para structs grandes (solo 8 bytes frente al tamaño total del struct)
  • Usa const con punteros cuando la función no deba modificar los datos

Los programadores de C suelen preferir pasar structs por puntero para obtener un mejor rendimiento.

Pruébalo tú mismo

#include <stdio.h>
#include <string.h>
#include "product.h"

int main() {
    char name[50];
    double price;
    int quantity;
    
    // Leer entradas
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: Crear una variable Product e inicializarla con los valores de entrada
    // Hint: Usar strcpy para copiar el nombre en el campo name de la struct
    
    // TODO: Llamar a display_by_value con el Product
    
    // TODO: Llamar a display_by_pointer con un puntero al Product
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming