Passagem de Ponteiros para Structs
Parte da seção Lógica e Fluxo do Journey de C da Coddy. Lição 47 de 63.
Embora passar structs por valor funcione bem para ler dados, isso se torna ineficiente com structs grandes, porque toda a estrutura é copiada. Mais importante ainda, você não pode modificar a struct original de dentro da função. É nesse ponto que passar ponteiros para structs se torna essencial.
Quando você passa um ponteiro para uma struct em vez da própria struct, a função recebe o endereço de memória da struct original. Essa abordagem oferece duas vantagens principais: é mais eficiente (não há cópia) e permite que a função modifique os dados originais.
A sintaxe de uma função que aceita um ponteiro para uma struct é:
void functionName(struct StructureName *ptr) {
// Corpo da função usando ptr->member
}Dentro da função, você usa o operador de seta para acessar e modificar os membros da struct. Quaisquer alterações feitas por meio do ponteiro afetarão diretamente a struct original na função chamadora, tornando essa abordagem perfeita para funções que precisam atualizar ou transformar dados de uma struct.
Esta técnica é fundamental para a construção de programas em C eficientes que trabalham com estruturas de dados complexas, pois combina o poder dos ponteiros com a organização de structs.
Desafio
FácilCrie um programa em C que demonstre a passagem de ponteiros para estruturas para funções, permitindo a modificação eficiente dos dados. Seu programa deve:
- Definir uma
structchamadaBankAccountcom os seguintes membros:- Um inteiro
accountNumberpara armazenar o número da conta - Um array de caracteres
ownerNamecom tamanho 30 para armazenar o nome do titular da conta - Um float
balancepara armazenar o saldo da conta - Um inteiro
transactionCountpara armazenar o número de transações
- Um inteiro
- Escrever uma função chamada
depositMoneyque:- Receba como parâmetros um ponteiro para uma estrutura
BankAccounte um valor float - Adicione o valor ao saldo da conta usando o operador de seta
- Incremente a contagem de transações em 1
- Imprima
Deposit successful. New balance: [balance]
- Receba como parâmetros um ponteiro para uma estrutura
- Escrever uma função chamada
withdrawMoneyque:- Receba como parâmetros um ponteiro para uma estrutura
BankAccounte um valor float - Verifique se o valor do saque é maior que o saldo atual
- Se não houver fundos suficientes, imprima
Insufficient funds. Current balance: [balance] - Se houver fundos suficientes, subtraia o valor do saldo, incremente a contagem de transações e imprima
Withdrawal successful. New balance: [balance]
- Receba como parâmetros um ponteiro para uma estrutura
- Escrever uma função chamada
displayAccountque:- Receba como parâmetro um ponteiro para uma estrutura
BankAccount - Imprima as informações da conta neste formato exato:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- Receba como parâmetro um ponteiro para uma estrutura
- Na função main:
- Crie uma variável
BankAccountchamadaaccount - Leia o número da conta, o nome do titular e o saldo inicial da entrada
- Defina a contagem de transações como 0
- Chame
displayAccountpara mostrar o estado inicial da conta - Leia um valor de depósito e chame
depositMoney - Leia um valor de saque e chame
withdrawMoney - Chame
displayAccountpara mostrar o estado final da conta
- Crie uma variável
Este desafio demonstra o poder de passar ponteiros para estruturas para funções. Diferentemente da passagem por valor, as funções recebem o endereço de memória da estrutura original, permitindo que modifiquem diretamente os dados originais. Essa abordagem é mais eficiente (não há cópia) e permite que as funções alterem permanentemente os valores da estrutura na função chamadora.
Experimente você mesmo
#include <stdio.h>
#include <string.h>
// TODO: Defina a struct BankAccount aqui
// TODO: Escreva a função depositMoney aqui
// TODO: Escreva a função withdrawMoney aqui
// TODO: Escreva a função displayAccount aqui
int main() {
// Ler entrada
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// TODO: Criar a variável BankAccount e inicializá-la
// TODO: Chamar displayAccount para mostrar o estado inicial
// TODO: Chamar depositMoney com o valor do depósito
// TODO: Chamar withdrawMoney com o valor do saque
// TODO: Chamar displayAccount para mostrar o estado final
return 0;
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Lógica e Fluxo
1Fundamentos de Ponteiros
O que é um Ponteiro?Declarando PonteirosO Operador de Endereço (&)O Operador de Desreferência (*)Ponteiros NULLRecapitulação: Fundamentos de Ponteiros4Projeto: Utilitário de Texto Simples
Visão Geral do ProjetoContando Caracteres2Ponteiros e Arrays
Nomes de Arrays como PonteirosElementos de Array - PonteirosAritmética de PonteirosComparando PonteirosRecapitulação: Percorrendo Arrays com Ponteiros5Ponteiros e Funções
Passagem por ValorPassando Ponteiros para FunçõesModificando Variáveis via PonteirosUm Exemplo Clássico: SwapPassando Arrays para FunçõesRecapitulação: Ponteiros como Argumentos8Structs e Ponteiros
Ponteiros para StructsO Operador Seta (->)Passagem de Structs por ValorPassagem de Ponteiros para StructsAlocação Dinâmica de StructsRecapitulação: Modificando Struct - Ptr3Arrays de Caracteres e Strings
Strings como Arrays de charO Terminador NuloEntrada de Strings com scanfUsando strlen()Usando strcpy()Usando strcat()Usando strcmp()Recapitulação: Funções Básicas de Strings6Gerenciamento de Memória
Memória Stack vs. HeapAlocação Dinâmica - malloc()Usando sizeof() para AlocaçãoVerificando Falhas de AlocaçãoLiberando Memória com free()Alocando com calloc()Recapitulação: Array Dinâmico9Projeto: Cadastro Simples de Contatos
Projeto: Definir a Struct de ContatoFunção para Criar um ContatoPratique por conta própria: Compilador de C online