Rappel sur les pointeurs void
Fait partie de la section Object Oriented Programming du Journey C de Coddy — leçon 49 sur 61.
Un void* est la façon dont le langage C dit « un pointeur vers quelque chose, mais je ne vous dis pas quoi ». Il peut contenir l'adresse de n'importe quel type de données — un int, un float, une structure ou n'importe quoi d'autre. Cela en fait le fondement de l'écriture de code générique en C.
Le piège est que vous ne pouvez pas déréférencer un void* directement. Le compilateur ne sait pas combien d'octets lire ni comment les interpréter. Pour utiliser les données, vous devez les transtyper (caster) vers le type correct :
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Cette flexibilité s'accompagne d'une responsabilité. Si vous effectuez un transtypage vers le mauvais type, le compilateur ne vous arrêtera pas — mais votre programme produira des résultats incohérents ou plantera. C'est pourquoi les fonctions génériques associent souvent un void* à un indicateur de type (comme une énumération ou un drapeau) afin que la fonction sache comment interpréter les données correctement.
Dans les prochaines leçons, vous utiliserez void* pour construire des conteneurs capables de stocker n'importe quel type de données, permettant ainsi de créer des structures de données véritablement réutilisables.
Défi
FacileÉcrivez une fonction appelée print_value qui accepte deux paramètres : un pointeur void* vers des données et un indicateur de type int. La fonction doit interpréter et afficher les données en fonction de l'indicateur de type :
- Si l'indicateur de type est
0, transtypez le pointeur enint*et affichez la valeur entière - Si l'indicateur de type est
1, transtypez le pointeur enfloat*et affichez la valeur flottante avec 2 décimales
Votre programme recevra deux entrées :
- Un indicateur de type (
0pour un entier,1pour un flottant) - Une valeur numérique
En fonction de l'indicateur de type, stockez la valeur dans le type de variable approprié, puis appelez print_value avec un pointeur vers cette variable et l'indicateur de type.
Exemple de sortie lorsque les entrées sont 0 et 42 :
42Exemple de sortie lorsque les entrées sont 1 et 3.14 :
3.14Exemple de sortie lorsque les entrées sont 0 et -17 :
-17Exemple de sortie lorsque les entrées sont 1 et 99.5 :
99.50Aide-mémoire
Un void* est un pointeur générique qui peut contenir l'adresse de n'importe quel type de données. Il offre de la flexibilité pour écrire du code générique en C.
Vous ne pouvez pas déréférencer un void* directement — vous devez d'abord le transtyper vers le type correct :
void print_int(void* data) {
int* p = (int*)data;
printf("%d\n", *p);
}
int main() {
int x = 42;
print_int(&x);
return 0;
}Les fonctions génériques associent souvent un void* à un indicateur de type (comme une énumération ou un drapeau) pour savoir comment interpréter les données correctement. Le transtypage vers le mauvais type peut provoquer un comportement indéfini ou des plantages.
Essayez vous-même
#include <stdio.h>
// À FAIRE : Écrivez votre fonction print_value ici
int main() {
int type_flag;
scanf("%d", &type_flag);
if (type_flag == 0) {
int int_value;
scanf("%d", &int_value);
// À FAIRE : Appelez print_value avec un pointeur vers int_value et le drapeau de type
} else if (type_flag == 1) {
float float_value;
scanf("%f", &float_value);
// À FAIRE : Appelez print_value avec un pointeur vers float_value et le drapeau de type
}
return 0;
}Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Bases de la programmation modulaire
Fichiers d'en-têteGardes d'inclusionFichiers sourcesFonctions statiquesRécapitulatif : Calculatrice modulaire4Encapsulation
Concept des pointeurs opaquesDéfinir des structures opaquesGetters et settersValidation dans les settersRécapitulatif : La boîte secrète7Pointeurs sur fonctions
Déclaration de pointeurs sur fonctionsAppel de pointeurs sur fonctionsTypedef pour les pointeurs sur fonctionsPassage de fonctions en argumentsRécapitulatif : Dispatcher de calculatrice10Conteneurs génériques
Rappel sur les pointeurs voidWrapper génériqueÉchange génériqueComparaison génériqueRappel : tableaux génériques2Objets et méthodes
Structs comme objetsLe pointeur 'Self'Rigueur du mot-clé constPointeur vs ValeurMéthodes utilitairesRécapitulatif : Point Manager5Projet : Compte bancaire simple
Configuration du projetImplémentation du compte8Polymorphisme
Pointeurs de fonctions dans les structuresSimulation de méthodesLe concept d'interfaceImplémentation d'interfacesItération polymorphiqueRécapitulatif : Greeter11Patrons de conception en C
Patron SingletonPatron FabriquePatron ItérateurRécapitulatif : Logger Factory3Cycle de vie des objets
Pattern de constructeurPattern de destructeurInitialisation sur la pileCopie profondeRécapitulatif : String Wrapper6Héritage par composition
Imbrication de structLa règle du premier membreAccès aux membres parentsUpcastingRécapitulatif : Hiérarchie des formes9Projet : Dessinateur de formes
Aperçu du projetImplémentation du cercle