Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. C++
  3. De C à C++
Extrait - C++ Des fondamentaux du langage aux applications (3e édition)
Extraits du livre
C++ Des fondamentaux du langage aux applications (3e édition) Revenir à la page d'achat du livre

De C à C++

Programmation structurée

Les langages de programmation ont commencé très tôt à assembler les instructions sous la forme de groupes réutilisables, les fonctions. Les variables ont naturellement pris le même chemin, bien qu’un peu plus tardivement.

Le tableau permet de traiter certains algorithmes, à condition que la donnée à traiter soit d’un type uniforme (char, int...). Lorsque la donnée à traiter contient des informations de natures différentes, il faut recourir à plusieurs tableaux, ou bien à un seul tableau en utilisant un type fourre-tout void*. Il faut bien le reconnaître, cette solution est à proscrire.

À la place, nous définissons des structures regroupant plusieurs variables appelées champs. Ces variables existent en autant d’exemplaires que souhaité, chaque exemplaire prenant le nom d’instance.

Le langage C++ connaît plusieurs formes composites :

  • les structures et les unions, aménagées à partir du C ;

  • les classes, qui seront traitées au chapitre suivant.

1. Structures

Les structures du C++ - comme celles du C - définissent de nouveaux types de données. Le nom donné à la structure engendre un type de données :

struct Personne 
{ 
  char nom[50]; 
  int age; 
} ; 

À partir de cette structure Personne, nous allons maintenant créer des variables, en suivant la syntaxe habituelle de déclaration qui associe un type et un nom :

Personne jean, albertine; 

jean et albertine sont deux variables du type Personne. Comme il s’agit d’un type non primitif (char, int...), on dit qu’il s’agit d’instances de la structure Personne. Le terme instance rappelle que le nom et l’âge sont des caractéristiques propres à chaque personne.

images/03ppn01.png

On utilise une notation particulière pour atteindre les champs d’une instance :

jean.age = 50;  // l'âge de jean 
printf("%s",albertine.nom); // le nom d'albertine 

Cette notation relie le champ à son instance.

a. Constitution d’une structure

Une structure peut contenir un nombre illimité de champ. Pour le lecteur qui découvre ce type de programmation et qui est habitué...

Gestion de la mémoire

La mémoire est vitale pour le système d’exploitation dont la tâche principale consiste à séparer chaque processus des autres, en lui allouant une quantité initiale de mémoire. Nous découvrons différentes stratégies d’allocation en fonction des systèmes. Les plus anciens (MS-DOS) et les plus basiques (sur microcontrôleur) adoptent une allocation par blocs d’une taille déterminée (64 ko par exemple), cette taille n’étant pas amenée à évoluer au cours du temps. D’autres systèmes ont recours à la pagination - une segmentation fine de l’espace mémoire en blocs de 4 ko -, ce qui autorise une gestion dynamique et efficace de la mémoire. Consécutivement à l’emploi de la mémoire paginée, l’adresse exprimée par un pointeur n’est jamais une adresse physique, mais logique, le microprocesseur se chargeant de la traduction.

Pour ce qui est du modèle applicatif, c’est-à-dire de la segmentation de la mémoire du processus, nous avons en général les zones suivantes :

images/03ppn02.png

Le langage C++ étant comme son prédécesseur très proche du système d’exploitation, il convient de bien connaître les différents types de gestion...

La bibliothèque standard du C

Avec les structures et l’allocation de la mémoire, nous nous rendons compte qu’un langage doit s’appuyer sur des librairies système pour construire des applications complètes. Le langage C++ possède sa propre librairie, mais nombre de programmeurs utilisent toujours les fonctions standards du langage C.

1. Les fonctions communes du langage C <stdlib.h>

La librairie standard stdlib.h contient des fonctions d’ordre général. Certaines fonctions peuvent être d’ailleurs déclarées dans d’autres en-têtes.

Voici une liste résumant quelques fonctions intéressantes pour le développement courant. Il est judicieux de consulter l’ouvrage de Kernighan et Ritchie ou bien une documentation fournie avec le compilateur pour connaître à la fois la liste complète des fonctions et en même temps leur signature.

Le Kernighan et Ritchie est l’ouvrage de référence écrit par les créateurs du langage C. Il est toujours édité et mis à jour à partir des évolutions du langage C.

Fonctions

Utilité

atoi, atof, strtod...

Fonctions de conversion entre un type chaîne et un type numérique.

getenv, setenv

Accès aux variables d’environnement système.

malloc, calloc

Allocation de mémoire.

rand, abs

Fonctions mathématiques.

La bibliothèque standard stdlib contient aussi des macros instructions basées sur la syntaxe #define :

Macro

Utilité

__min, __max

Donne les valeurs min et max de deux arguments.

NULL

Littéralement (void*)0.

Un petit exemple montre comment utiliser la bibliothèque :

char* lecture = new char[500]; 
printf("Nombre ? "); 
scanf("%s",lecture); 
 
double nombre = atof(lecture); 
double pi = 3.14159265358; 
 
printf("Le nombre le plus grand est %2f\n",__max(nombre,pi)); 
images/02RI02.png

2. Chaînes <string.h>

Le langage C++ gère toujours ses littérales de chaîne au format char* défini par le langage C. Aussi est-il important de connaître les principales fonctions de la bibliothèque string.h.

Fonctions

Utilité

memcpy, memcmp, memset

Vision mémoire des chaînes de caractères : copie, comparaison...

Travaux pratiques

1. Chargement de scripts dans tiny-lisp

Le module Labmain.cpp définit la fonction load_script() utilisée pour charger un script en mémoire et lui appliquer la coloration syntaxique. Cette fonction s’appuie sur une version sécurisée de la librairie stdlib, et ses méthodes sont reconnaissables par leur suffixe _s (pour secure).

#pragma region load_script 
void load_script(char*filename,bool show_script=false) 
{ 
   string script; 
  FILE* f = NULL; 
  try  
  { 
     // utilise la version sûre du C++ Runtime 
     int err = fopen_s(&f,(const char *)filename, "rb"); 
     if (err != 0) 
     { 
        cerr << "erreur d'ouverture de " << filename << endl; 
        return; 
     } 
      
     int c; 
     char buf[4001]; 
     while ((c = fread(buf, 1, 4000, f)) > 0) 
     { 
        buf[c] = 0; 
        script.append((char*)buf); 
     } 
     fclose(f); 
     f = NULL; 
 
     if (show_script) { ...