L’arrivé du C++17 – Les changements sur les littéraux

Ce nouvel article traite des changements apportés aux littéraux dans C++17 : les littéraux flottants hexadécimaux et les nouveaux caractères litéraux UTF-8. Les documents P0245 “Hexadecimal floating literals for C++” et N4264 (“Adding u8 character literals”) présentent ces modifications.

Les littéraux flottants hexadécimaux

La P0245 apporte le support du format hexadécimal pour les littéraux flottants.

Etant donné que le symbole e  est un chiffre hexadécimal, le symbole p  est utilisé pour séparer la mantisse (la significande) et l’exposant :

Le résultat va peut-être en déconcerter certains. En fait, si la mantisse est effectivement en base 16, l’exposant lui est décimal et la mantisse est multipliée par 2 puissance l’exposant. Le nombre final est donc : n = mantisse*2exposant.

Pour faire clair, 0xa0p2 peut se décomposer de la sorte :

    • La mantisse vaut A016 = 101000002 = 16010.
    • L’exposant vaut 210.
    • Le nombre final vaut 160*22 = 160*4 = 64010.

Voici quelques exemples de littéraux hexadécimaux :

Les suffixes f  et L  sont également utilisables pour la notation hexadécimale. Notez que de façon assez étonante, il est obligatoire de spécifier un exposant pour un littéral hexadécimal :

La précision des nombres en virgule flottante n’est pas parfaite. Il peut être interessant d’avoir des flottants codés en durs avec une valeur exacte afin d’éviter les variantes de conversion. Par exemple, le nombre 0.110 n’est pas représentable de façon exacte avec une représentation binaire (même si en théorie rien n’oblige la plateforme cible à utiliser une représentation IEEE 754, il s’agit tout de même de l’immense majorité), il sera converti en 0.10000000000000032 ou 0.09999999999999972 d’une manière générale.

Si vous souhaitez forcer l’une ou l’autre de ces représentations, alors la notation hexadécimale facilite la tâche en permettant de spécifier une représentation binaire précise. Anciennement, il fallait par exemple s’amuser avec des reinterpret_cast  depuis des plages de bytes (comme des unsigned char ) préparées.

Les caractères UTF-8

Le C++17 apporte aussi la possibilité d’utiliser le préfixe u8  sur les caractères avec la N4264, celui-ci étant déjà disponible pour les chaînes de caractère depuis C++11.

Un caractère précédé de u8  est donc un caractère litéral UTF-8 (UTF-8 character literal). Il s’agit d’un char  dont la valeur est égale à la valeur UTF-8 (ISO 10646) du caractère.

Notez que si le caractère n’est pas représentable en UTF-8 avec un seul byte, le littéral n’est pas valide (et on se demande pourquoi la gestion de l’UTF-8 en C++ est considérée comme catastrophique) :

Références
%d bloggers like this: