web-dev-qa-db-fra.com

Quel est le but d'un "+" unaire avant un appel aux membres de std :: numeric_limits <unsigned char>?

J'ai vu cet exemple dans la documentation de cppreference pour std::numeric_limits

#include <limits>
#include <iostream>

int main() 
{
    std::cout << "type\tlowest()\tmin()\t\tmax()\n\n";

    std::cout << "uchar\t"
              << +std::numeric_limits<unsigned char>::lowest() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::min() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::max() << '\n';
    std::cout << "int\t"
              << std::numeric_limits<int>::lowest() << '\t'
              << std::numeric_limits<int>::min() << '\t'
              << std::numeric_limits<int>::max() << '\n';
    std::cout << "float\t"
              << std::numeric_limits<float>::lowest() << '\t'
              << std::numeric_limits<float>::min() << '\t'
              << std::numeric_limits<float>::max() << '\n';
    std::cout << "double\t"
              << std::numeric_limits<double>::lowest() << '\t'
              << std::numeric_limits<double>::min() << '\t'
              << std::numeric_limits<double>::max() << '\n';
}

Je ne comprends pas l'opérateur "+" dans

<< +std::numeric_limits<unsigned char>::lowest()

Je l'ai testé, remplacé par "-", et cela a également fonctionné. A quoi sert un tel opérateur "+"?

128
Zhang

L'opérateur de sortie << lorsqu'il reçoit un char (signé ou non signé) l'écrira sous la forme d'un caractère .

Ces fonctions renverront des valeurs de type unsigned char. Et comme indiqué ci-dessus, les caractères que ces valeurs représentent dans l’encodage actuel sont imprimés, pas leurs valeurs entières.

L'opérateur + convertit le unsigned char renvoyé par ces fonctions en une int à promotion d'un entier . Ce qui signifie que les valeurs entières seront imprimées à la place.

Une expression comme +std::numeric_limits<unsigned char>::lowest() est essentiellement égale à static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

135

+ est là pour transformer le unsigned char en int. L'opérateur + préserve la valeur, mais il a pour effet d'induire une promotion intégrale sur son opérande. C'est pour s'assurer que vous voyez une valeur numérique au lieu d'un caractère (semi-) aléatoire que operator << imprimera lorsqu'un type de caractère lui est attribué.

37
StoryTeller

Juste pour ajouter une référence aux réponses déjà données. D'après le brouillon standard du RPC N471 :

8.5.2.1 Opérateurs unaires
...

  1. L'opérande de l'opérateur unaire + doit avoir un type arithmétique, une énumération non délimitée ou un pointeur et le résultat correspond à la valeur de l'argument. La promotion intégrale est effectuée sur des opérandes d'intégration ou d'énumération. Le type du résultat est le type de l'opérande promu.

Et char, short, int et long sont des types entiers.

18
P.W

Sans _+_, le résultat sera différent. L'extrait de code suivant génère _a 97_ au lieu de _a a_

_char ch = 'a';
std::cout << ch << ' ' << +ch << '\n';
_

La raison en est que des surcharges différentes impriment différents types de données . Il n'y a pas de surcharge basic_ostream& operator<<( char value ); pour std::basic_ostream et c'est expliqué à la fin de la page.

Les arguments de caractères et de chaînes de caractères (par exemple, de type char ou _const char*_) sont gérés par le surcharges non membres de _operator<<_. Tenter de générer un caractère à l’aide de la syntaxe d’appel de la fonction membre (par exemple, std::cout.operator<<('c');) appelle l’une des surcharges (2-4) et génère la valeur numérique . Tenter de générer une chaîne de caractères à l'aide de la syntaxe d'appel de fonction membre appelle overload (7) et affiche la valeur du pointeur à la place.

Le surcharge non-membre qui sera appelé lorsque vous passerez une variable char est

_template< class CharT, class Traits> basic_ostream<CharT,Traits>& operator<<(
    basic_ostream<CharT,Traits>& os, char ch );
_

qui affiche le caractère au point de code ch

Donc, si vous passez char, _signed char_ ou _unsigned char_ directement au flux, le caractère sera imprimé. Si vous essayez de supprimer le _+_ des lignes ci-dessus, vous verrez qu'il imprime des caractères "étranges" ou non visibles, ce qui n'est pas ce à quoi on pourrait s'attendre.

Si vous voulez plutôt leurs valeurs numériques, vous devez appeler la surcharge pour short, int, long ou _long long_. La méthode la plus simple consiste à passer de char à int avec unary plus _+_. C'est l'un des applications utiles rares de opérateur unaire plus . Une conversion explicite en int fonctionnera également

Il y a beaucoup de gens qui ont fait face à ce problème sur SO comme

12
phuclv