Adloun

Probleme – Le type somme d'OCaml contre l'union de C

Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 6 — Types et structures de données abstraites

Énoncé

On veut représenter une valeur qui est soit un entier, soit une chaîne.

Corrigé

1. Les deux versions, et la mesure.


union brut { int i; char s[8]; };     /* les deux champs au MEME endroit */

on ecrit la chaine "abc", on relit l'entier : 6513249
on ecrit l'entier 1633837568, on relit la chaine : ""
sizeof(union brut) = 8

Le nombre n'est pas arbitraire : c'est , soit les octets 'a', 'b', 'c', ' 0' relus comme un entier de quatre octets en petit-boutiste. Une union ne retient pas ce qu'on y a mis : elle superpose deux lectures des mêmes octets, et le langage ne signale rien.

En OCaml, le type somme porte l'information dans la valeur :


type valeur = Entier of int | Chaine of string
let afficher = function
  | Entier i -> Printf.printf "entier %d\n" i
  | Chaine s -> Printf.printf "chaine %s\n" s

2. L'étiquette, et ce qui reste. On adjoint à l'union un champ qui dit quel membre est valide :


enum sorte { ENTIER, CHAINE };
struct valeur { enum sorte sorte; union { int i; char s[8]; } u; };

Mesuré : sizeof(struct valeur) vaut contre pour l'union nue — quatre octets pour l'étiquette. La lecture devient sûre si l'étiquette dit vrai. Or rien ne l'y oblige :


struct valeur menteur = { CHAINE, { .i = 42 } };   /* etiquette FAUSSE */
/* afficher(&menteur) imprime : chaine "*"   -- 42 est le code de '*' */

L'étiquette est une convention, pas une garantie. Elle déplace la faute possible de la lecture vers l'écriture ; elle ne la supprime pas. Pour la supprimer, il faudrait rendre la structure opaque et n'offrir que deux constructeurs — c'est-à-dire refaire à la main ce qu'OCaml donne.

3. Les deux services d'OCaml.


Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched: Flottant _

Aucun switch de C ne donne cela : un default silencieux ou un cas oublié se compilent sans un mot.

La morale, qui vaut pour tout le chapitre. L'union de C et le type somme d'OCaml décrivent la même chose et occupent presque la même mémoire. Ce qui les sépare n'est pas la représentation, c'est ce que le compilateur promet de vérifier. Un type n'est pas une manière de ranger des octets : c'est un contrat, et sa valeur se mesure à ce qu'il refuse.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.