Menu
CoddyTech

Ponteiro vs. valor

Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 9 de 61.

Quando você passa uma struct para uma funçã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 faz uma diferença significativa no desempenho.

A passagem por valor cria uma cópia completa da struct na pilha. Para uma struct pequena com alguns números inteiros, isso não é problema. 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 é diferente. Com um parâmetro de valor, você usa o operador ponto (s.name). Com um ponteiro, você usa o operador seta (s->name).

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

É por isso que programadores de 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 eficiência e clareza de intenção.

challenge icon

Desafio

Fácil

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

Você criará três arquivos:

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

Você receberá três entradas: o nome do produto (uma string), o preço (um double) e a quantidade (um inteiro).

No seu arquivo principal, inicialize um Product com esses valores e, em seguida, chame display_by_value seguido de display_by_pointer.

As duas funções devem exibir as informações neste formato:

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

Use %.2f para exibir o preço com 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;
    
    // Leia as entradas
    scanf("%s", name);
    scanf("%lf", &price);
    scanf("%d", &quantity);
    
    // TODO: Crie uma variável Product e inicialize-a com os valores de entrada
    // Dica: Use strcpy para copiar o nome para o campo name da struct
    
    // TODO: Chame display_by_value com o Product
    
    // TODO: Chame 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 Programação Orientada a Objetos

Pratique por conta própria: Compilador de C online