Pointeur vs Valeur
Fait partie de la section Object Oriented Programming du Journey C de Coddy — leçon 9 sur 61.
Lorsque vous passez une structure à une fonction, le langage C vous offre deux options : la passer par valeur (copier l'intégralité de la structure) ou la passer par pointeur (copier uniquement l'adresse). Ce choix a un impact significatif sur les performances.
Le passage par valeur crée une copie complète de la structure sur la pile. Pour une petite structure avec quelques entiers, cela ne pose pas de problème. Mais imaginez une structure de plusieurs centaines d'octets — chaque appel de fonction copie toutes ces données :
typedef struct {
char name[100];
int scores[50];
double average;
} Student;
// Par valeur : copie ~608 octets à chaque appel
void print_by_value(Student s) {
printf("%s: %.2f\n", s.name, s.average);
}
// Par pointeur : copie seulement 8 octets (l'adresse)
void print_by_pointer(const Student *s) {
printf("%s: %.2f\n", s->name, s->average);
}
La syntaxe diffère également. Avec un paramètre de valeur, vous utilisez l'opérateur point (s.name). Avec un pointeur, vous utilisez l'opérateur flèche (s->name).
La version avec pointeur est plus efficace car elle ne transmet qu'une adresse mémoire — généralement 8 octets, quelle que soit la taille de la struct.
C'est pourquoi les programmeurs C passent presque toujours les structures par pointeur. Utilisez const lorsque la fonction ne doit pas modifier les données, et un pointeur classique lorsqu'elle le doit. Vous obtenez à la fois de l'efficacité et une intention claire.
Défi
FacileConstruisons un module Product qui démontre la différence entre le passage de structures par valeur et par pointeur. Vous allez créer deux fonctions d'affichage : une qui reçoit la structure entière sous forme de copie, et une qui reçoit simplement un pointeur vers celle-ci.
Vous allez créer trois fichiers :
product.h: Déclarez une structureProductavec trois membres :char name[50],double price, etint quantity. Déclarez également deux fonctions :display_by_value— prend unProductpar valeur et affiche ses informationsdisplay_by_pointer— prend unconst Product *et affiche les mêmes informations
PRODUCT_H.product.c: Implémentez les deux fonctions. Notez la différence de syntaxe : la version par valeur utilise l'opérateur point (p.name), tandis que la version par pointeur utilise l'opérateur flèche (p->name). Les deux fonctions doivent afficher les données dans le même format.main.c: Créez un Product, puis appelez les deux fonctions d'affichage pour montrer qu'elles produisent une sortie identique malgré l'utilisation de styles de paramètres différents.
Vous recevrez trois entrées : le nom du produit (une chaîne de caractères), le prix (un double), et la quantité (un entier).
Dans votre fichier principal, initialisez un Product avec ces valeurs, puis appelez display_by_value suivi de display_by_pointer.
Les deux fonctions doivent imprimer dans ce format :
Product: {name}, Price: {price}, Qty: {quantity}Utilisez %.2f pour le prix afin d'afficher deux décimales.
Par exemple, avec les entrées Laptop, 999.99, et 5, la sortie serait :
Product: Laptop, Price: 999.99, Qty: 5
Product: Laptop, Price: 999.99, Qty: 5Aide-mémoire
Lorsque vous passez des structures à des fonctions, vous pouvez choisir entre le passage par valeur (copie de l'intégralité de la structure) ou le passage par pointeur (copie de l'adresse uniquement).
Le passage par valeur crée une copie complète de la structure :
void print_by_value(Student s) {
printf("%s: %.2f\n", s.name, s.average); // Utilisez l'opérateur point
}
Le passage par pointeur ne transmet que l'adresse mémoire :
void print_by_pointer(const Student *s) {
printf("%s: %.2f\n", s->name, s->average); // Utilisez l'opérateur flèche
}
Différences clés :
- Par valeur utilise l'opérateur point (
s.member) - Par pointeur utilise l'opérateur flèche (
s->member) - Les pointeurs sont plus efficaces pour les structures volumineuses (seulement 8 octets contre la taille totale de la structure)
- Utilisez
constavec les pointeurs lorsque la fonction ne doit pas modifier les données
Les programmeurs C préfèrent généralement passer les structures par pointeur pour de meilleures performances.
Essayez vous-même
#include <stdio.h>
#include <string.h>
#include "product.h"
int main() {
char name[50];
double price;
int quantity;
// Lire les entrées
scanf("%s", name);
scanf("%lf", &price);
scanf("%d", &quantity);
// TODO : Créer une variable Product et l'initialiser avec les valeurs d'entrée
// Conseil : Utiliser strcpy pour copier le nom dans le champ name de la structure
// TODO : Appeler display_by_value avec le Product
// TODO : Appeler display_by_pointer avec un pointeur vers le Product
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ète2Objets 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