Revisão de Ponteiros Void
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 49 de 61.
Um void* é a maneira do C dizer "um ponteiro para algo, mas não vou te dizer o quê". Ele pode conter o endereço de qualquer tipo de dado — um int, um float, uma struct ou qualquer outra coisa. Isso o torna 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 ler ou como interpretá-los. Para usar os dados, você deve convertê-los (cast) 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 com responsabilidade. Se você fizer o cast para o tipo errado, o compilador não irá impedi-lo — mas seu programa produzirá lixo ou irá travar. É por isso que funções genéricas frequentemente emparelham um void* com um indicador de tipo (como um enum ou flag) para que a função saiba como interpretar os dados corretamente.
Nas próximas lições, você usará void* para construir containers que podem 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 dados e uma flag de tipo int. A função deve interpretar e imprimir os dados com base na flag de tipo:
- Se a flag de tipo for
0, faça o cast do ponteiro paraint*e imprima o valor inteiro - Se a flag de tipo for
1, faça o cast do ponteiro parafloat*e imprima o valor float com 2 casas decimais
Seu programa receberá duas entradas:
- Uma flag de tipo (
0para inteiro,1para float) - Um valor numérico
Com base na flag 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 a flag 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.50Folha de consulta
Um void* é um ponteiro genérico que pode conter o endereço de qualquer tipo de dado. Ele fornece flexibilidade para escrever código genérico em C.
Você não pode desreferenciar um void* diretamente — você deve convertê-lo para o tipo correto primeiro:
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Funções genéricas frequentemente associam um void* com um indicador de tipo (como um enum ou flag) para saber como interpretar os dados corretamente. A conversão para o tipo errado pode causar comportamento indefinido ou falhas.
Experimente 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 a flag 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 a flag 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 Object Oriented Programming
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta7Ponteiros para Funções
Declarando Ponteiros para FunçõesChamando Ponteiros para FunçõesTypedef para Ponteiros para FunçõesPassando Funções como ArgumentosRecapitulação: Dispatch de Calculadora10Contêineres Genéricos
Revisão de Ponteiros VoidWrapper GenéricoTroca GenéricaComparação GenéricaRevisão: Array Genérico2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do Círculo