Ansi/iso c++ : 002 : types numériques

Contenu du snippet

Une des premières choses que l’on souhaite connaître d’un langage de programmation sont les types fondamentaux.
Ici, je vous présente les types numériques.
La norme ANSI/ISO C++ définit les types numériques selon des règles simples qui laisse beaucoup de liberté aux différentes implémentations[1].
C’est pourquoi je vous propose un petit programme qui va vous permettre de connaître les limites des différents types numériques selon l’implémentation[1].

Source / Exemple :


#include <iostream>
#include <iomanip>
#include <limits>

int main()
{
   using namespace std;

   cout
      << "float :" << endl
         << "  digits10 = " << numeric_limits<float>::digits10 << endl
         << setprecision( numeric_limits<float>::digits10 )
         << "  min = " << numeric_limits<float>::min() << endl
         << "  max = " << numeric_limits<float>::max() << endl
      << "double :" << endl
         << "  digits10 = " << numeric_limits<double>::digits10 << endl
         << setprecision( numeric_limits<double>::digits10 )
         << "  min = " << numeric_limits<double>::min() << endl
         << "  max = " << numeric_limits<double>::max() << endl
      << "long double :" << endl
         << "  digits10 = " << numeric_limits<long double>::digits10 << endl
         << setprecision( numeric_limits<long double>::digits10 )
         << "  min = " << numeric_limits<long double>::min() << endl
         << "  max = " << numeric_limits<long double>::max() << endl
      << endl
      << "press enter to continue" << endl
   ;

   cin.ignore( 1, '\n');

   cout
      << "short :" << endl
         << "  min = " << numeric_limits<short>::min() << endl
         << "  max = " << numeric_limits<short>::max() << endl
      << "unsigned short :" << endl
         << "  min = " << numeric_limits<unsigned short>::min() << endl
         << "  max = " << numeric_limits<unsigned short>::max() << endl
      << "int :" << endl
         << "  min = " << numeric_limits<int>::min() << endl
         << "  max = " << numeric_limits<int>::max() << endl
      << "unsigned int :" << endl
         << "  min = " << numeric_limits<unsigned int>::min() << endl
         << "  max = " << numeric_limits<unsigned int>::max() << endl
      << "long :" << endl
         << "  min = " << numeric_limits<long>::min() << endl
         << "  max = " << numeric_limits<long>::max() << endl
      << "unsigned long :" << endl
         << "  min = " << numeric_limits<unsigned long>::min() << endl
         << "  max = " << numeric_limits<unsigned long>::max() << endl
      << endl
      << "press enter to continue" << endl
   ;

   cin.ignore( 1, '\n');

   cout
      << "char :" << endl
         << "  min = "
            << static_cast<int>( numeric_limits<char>::min() ) << endl
         << "  max = "
            << static_cast<int>( numeric_limits<char>::max() ) << endl
      << "wchar_t :" << endl
         << "  min = " << numeric_limits<wchar_t>::min() << endl
         << "  max = " << numeric_limits<wchar_t>::max() << endl
      << "unsigned char :" << endl
         << "  min = "
            << static_cast<int>( numeric_limits<unsigned char>::min() ) << endl
         << "  max = "
            << static_cast<int>( numeric_limits<unsigned char>::max() ) << endl
      << "signed char :" << endl
         << "  min = "
            << static_cast<int>( numeric_limits<signed char>::min() ) << endl
         << "  max = "
            << static_cast<int>( numeric_limits<signed char>::max() ) << endl
      << "bool :" << endl
         << "  min = " << numeric_limits<bool>::min() << endl
         << "  max = " << numeric_limits<bool>::max() << endl
      << endl
      << "press enter to exit" << endl
   ;

   cin.ignore( 1, '\n');
}

Conclusion :


Ici, nous incluons les déclarations des objets[2] standard ayant trait au flux d’entrée-sortie, aux manipulateurs d’entrée-sortie (précision des réels) et les limites.
Nous déclarons, qu’à l’intérieur de la fonction main, nous utiliserons (par défaut) des objets standard. Cela nous évitera les préfix récurrents 'std::'[3] sinon utile à chaque référence d’un objet standard.
Nous savons que les algorithmes, en C++, sont organiser sous forme de fonction. Au sein d’une fonction, un algorithme est constitué d’instructions. Deux instructions consécutives sont bien séparées d’un point virgule ;. Je confirme car vous pourriez être étonné de n’en voir pas beaucoup ici. Le fait est qu’une instruction peut-être très longue.
L’indentation que j’utilise permet de bien comprendre le but de la manœuvre. 'cout', le flux de sortie, est utilisé pour envoyer plusieurs choses, les unes après les autres.
"numeric_limits" est un objet standard, déclaré dans <limits>, capable de fournir une foule d’informations concernant les limites des différents types numériques. L’objet doit être décliné selon le type "numeric_limits<nom_du_type>". Les différentes informations s’obtiennent alors soit par l’appel d’une fonction ("numeric_limits<float>::min()"[4]), soit par la consultation d’une constante ("numeric_limits<float>::digits10"[4]). Les informations qui nous importent sont, pour les réels : la précision en base 10, la plus petite et la plus grande valeur. Pour les nombres entiers, uniquement les deux valeurs limites.
"cin.ignore( 1, '\n');" est utiliser pour interrompre le cours d’exécution des instruction tant que touche la touche "Enter" n’est pressé. C’est l’effet obtenu par l’appel d’une fonction de l’objet représentant les flux d’entré. Il n’est vraiment pas utile ici de connaître le rôle de cette fonction ou les valeurs passées en arguments. Retenez seulement que le clavier n’a pas d’existence propre dans le standard, qu’il n’existe donc aucune fonction du genre "clavier.attendre_touche_presse()". Typiquement, le clavier est géré par le système et câblé, par défaut, comme entrée aux programmes exécutés. C++ gère les entrés, comme les sorties, sous forme de flux (stream en anglais), imaginer une rivière sur laquelle vogue les caractères. Ici, nous attendons de pouvoir ignorer l’un de ses caractères.

Les 3 types de réels : 'float', 'double' et 'long double' (souvent identique à 'double').

Les 3 types d’entiers : 'int', 'short int' (plus petit ou identique à 'int') et 'long' (plus grand ou identique à 'int').
Par défaut ils sont, comme on dit signé, c’est à dire qu’ils recouvrent un domaine de valeurs négatives et positives. Par l’ajout du préfix 'signed' on explicite la chose. Par l’ajout du préfix 'unsigned' on obtient ces mêmes types exclusivement dédiés aux valeurs positives.

Les deux type utilisé pour stocker des code de caractère sont 'char' (typiquement un octet, byte) et 'w_char' (typiquement de quoi stocker un unicode, soit 2 octets). Ces types peuvent être employés pour stocker des entiers. Néanmoins, ils doivent être convertis en 'int' dès lors que l’on souhaite afficher (cout <<) l’entier et non pas le caractère en question. D’où le "static_cast< type_désiré >( ce_qu_il_faut_convertir )"[5].
'bool' peut-être considéré comme un entier dont le domaine de valeurs ne comprend que 0 et 1. Mais il s’agît surtout d’un type booléen pour lequel il est plus naturel de considérer ses 2 états possibles 'true' (vrai) et 'false' (faux).

[1] : Nous parlons ici d’implémentation du ANSI/ISO C++. C’est à dire du compilateur (GCC, Intel, Borland, etc.) mais également de la plate-forme (Win32, Linux, etc.) visée. Une chose extrêmement importante également est la configuration du compilateur, qui peut modifier sont comportement, son rapprochement à la norme etc.

[2] : Nous parlons ici d’objet au sens large. Ces objets peuvent être des fonctions, des types, des variables etc.

[3] : 'std::' indique un espace de nomage. Nous verrons cela plus tard.

[4] : L’objet en question est, en l’occurrence, un modèle de classe. Sa déclinaison donne lieux à une classe à part entière. Aucun objet ne doit être instancié de ces classes car touts les membres sont statiques, c’est à dire qu’ils ne dépendent pas d’une instance en particulier. Ainsi, nous atteignons les différent membre "nom_de_la_classe::nom_du_membre_statique". Pour les membre de type fonction, nous ajoutons les parenthèse (vide car aucun argument). Pour les membres de type constante (variable), nous ne mettons rien d’autre. Nous parlerons plus tard des classes et des modèles de classes.

[5] : C’est ce que l’on appèle un opérateur de conversion ou "cast operator". C++ en possède 4. Celui-ci sert à explicité une conversion légitime mais pas évidente (pour le compilateur). Ici, il n’était pas évident que nous voulion afficher le char en tant qu’entier et non pas en tant que caractère.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.