Revisão de ponteiros void
Parte da seção Programação Orientada a Objetos do Journey de C da Coddy. Lição 49 de 61.
Um void* é a maneira de C dizer “um ponteiro para alguma coisa, mas não vou dizer o quê”. Ele pode armazenar o endereço de qualquer tipo de dado: um int, um float, uma struct ou qualquer outra coisa. Isso faz dele a base para escrever código genérico em C.
O problema é que você não pode desreferenciar um void* diretamente. O compilador não sabe quantos bytes deve ler nem como interpretá-los. Para usar os dados, você precisa convertê-lo de volta para o tipo correto:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Essa flexibilidade vem acompanhada de responsabilidade. Se você converter para o tipo errado, o compilador não vai impedir você, mas seu programa produzirá resultados sem sentido ou travará. Por isso, funções genéricas costumam combinar um void* com um indicador de tipo (como um enum ou uma flag), para que a função saiba como interpretar os dados corretamente.
Nas próximas lições, você usará void* para criar contêineres capazes de armazenar qualquer tipo de dado, permitindo estruturas de dados verdadeiramente reutilizáveis.
Desafio
FácilEscreva uma função chamada print_value que aceite dois parâmetros: um ponteiro void* para os dados e um indicador de tipo int. A função deve interpretar e imprimir os dados com base no indicador de tipo:
- Se o indicador de tipo for
0, converta o ponteiro paraint*e imprima o valor inteiro - Se o indicador de tipo for
1, converta o ponteiro parafloat*e imprima o valor de ponto flutuante com 2 casas decimais
Seu programa receberá duas entradas:
- Um indicador de tipo (
0para inteiro,1para ponto flutuante) - Um valor numérico
Com base no indicador de tipo, armazene o valor no tipo de variável apropriado e, em seguida, chame print_value com um ponteiro para essa variável e o indicador de tipo.
Exemplo de saída quando as entradas são 0 e 42:
42Exemplo de saída quando as entradas são 1 e 3.14:
3.14Exemplo de saída quando as entradas são 0 e -17:
-17Exemplo de saída quando as entradas são 1 e 99.5:
99.50Experimente você mesmo
#include <stdio.h>
// TODO: Escreva sua função print_value aqui
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// TODO: Chame print_value com um ponteiro para int_value e o indicador de tipo
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// TODO: Chame print_value com um ponteiro para float_value e o indicador de tipo
}
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 Programação Orientada a Objetos
1Fundamentos da Programação Modular
Arquivos de cabeçalhoProteções de inclusãoArquivos-fonteFunções estáticasRevisão: calculadora modular4Encapsulamento
Conceito de ponteiros opacosDefinindo structs opacasGetters e settersValidação em settersRevisão: caixa secreta7Ponteiros para Funções
Declarando Ponteiros para FunçõesChamando Ponteiros para FunçõesTypedef para Ponteiros para FunçõesPassando Funções como ArgumentosRevisão: Despacho da Calculadora10Contêineres Genéricos
Revisão de ponteiros voidInvólucro genéricoTroca genéricaComparação genéricaRevisão: array genérico2Objetos e métodos
Structs como objetosO ponteiro 'Self'Correção de constPonteiro vs. valorMétodos auxiliaresRevisão: Gerenciador de pontos5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de vida do objeto
Padrão de construtorPadrão de destrutorInicialização da pilhaCópia profundaRevisão: wrapper de String6Herança por composição
Incorporação de structRegra do primeiro membroAcessando membros do tipo paiUpcastingRevisão: hierarquia de formas9Projeto: Desenhador de Formas
Visão geral do projetoImplementação do círculoImplementação do retânguloUso polimórficoContêiner de formasPratique por conta própria: Compilador de C online