Menu
Coddy logo textTech

Ponteiro vs Valor

Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 9 de 61.

Quando você passa uma struct para uma função, o C oferece duas opções: passá-la por valor (copiar a struct inteira) ou passá-la por ponteiro (copiar apenas o endereço). A escolha é significativamente importante para o desempenho.

A passagem por valor cria uma cópia completa da struct na pilha. Para uma struct pequena com alguns inteiros, isso é aceitável. Mas imagine uma struct com centenas de bytes — cada chamada de função copia todos esses dados:

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

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

// Por ponteiro: copia apenas 8 bytes (o endereço)
void print_by_pointer(const Student *s) {
    printf("%s: %.2f\n", s->name, s->average);
}

A sintaxe também difere. Com um parâmetro de valor, você usa o operador de ponto (s.name). Com um ponteiro, você usa o operador de seta (s->name).

A versão com ponteiro é mais eficiente porque ela passa apenas um endereço de memória — tipicamente 8 bytes, independentemente do tamanho da struct.

É por isso que programadores C quase sempre passam structs por ponteiro. Use const quando a função não deve modificar os dados, e um ponteiro comum quando deve. Você obtém tanto eficiência quanto uma intenção clara.

challenge icon

Desafio

Fácil

Vamos construir um módulo Product que demonstra a diferença entre passar structs por valor e por ponteiro. Você criará duas funções de exibição — uma que recebe a struct inteira como uma cópia e outra que recebe apenas um ponteiro para ela.

Você criará três arquivos:

  • product.h: Declare uma struct Product com três membros: char name[50], double price e int quantity. Também declare duas funções:
    • display_by_value — recebe um Product por valor e imprime suas informações
    • display_by_pointer — recebe um const Product * e imprime as mesmas informações
    Use guards de inclusão com o símbolo PRODUCT_H.
  • product.c: Implemente ambas as funções. Observe a diferença de sintaxe: a versão por valor usa o operador ponto (p.name), enquanto a versão por ponteiro usa o operador seta (p->name). Ambas as funções devem imprimir no mesmo formato.
  • main.c: Crie um Product, então chame ambas as funções de exibição para mostrar que elas produzem uma saída idêntica, apesar de usarem estilos de parâmetros diferentes.

Você receberá três entradas: o product name (uma string), o price (um double) e a quantity (um inteiro).

No seu arquivo principal, inicialize um Product com esses valores, então chame display_by_value seguido por display_by_pointer.

Ambas as funções devem imprimir neste formato:

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

Use %.2f para o preço para exibir duas casas decimais.

Por exemplo, com as entradas Laptop, 999.99 e 5, a saída seria:

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

Experimente você mesmo

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

int main() {
    char name[50];
    double price;
    int quantity;
    
    // Ler as entradas
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: Criar uma variável Product e inicializá-la com os valores de entrada
    // Dica: Use strcpy para copiar o nome para o campo name da struct
    
    // TODO: Chamar display_by_value com o Product
    
    // TODO: Chamar display_by_pointer com um ponteiro para o Product
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming