À quoi sert un «+» unaire avant un appel aux membres std :: numeric_limits <unsigned char>?

130

J'ai vu cet exemple dans la documentation de cppreference pourstd::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 "+"?

Zhang
la source
3
Essayez-le. Qu'est-ce que vous obtenez si vous omettez le +?
Pete Becker
4
Cette question n'aurait pas besoin d'être posée si l'auteur du code se soucie d'expliquer ce que cela signifie ou d'utiliser un cast explicite à la place ...
user202729
si vous remplacez par -alors les sorties ne seront pas les valeurs correctes pour les limites
phuclv
1
Pour mémoire, si vous voulez rechercher ce genre de chose sur Google en vous-même, cela s'appelle l'opérateur "unaire plus" - il est unaire car il prend une valeur unique (dans ce cas, la chose juste après), et "plus "est la façon de dire adaptée à Google +. Dans ce cas, votre requête serait probablement "c ++ unaire plus". Ce n'est ... pas vraiment intuitif, et vous devez encore apprendre à lire la documentation que vous trouverez, mais IMO c'est une compétence utile à cultiver.
Fund Monica's Lawsuit

Réponses:

137

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

Ces fonctions renverront des valeurs de type unsigned char. Et comme indiqué ci-dessus, cela affichera les caractères que ces valeurs représentent dans l'encodage actuel, et non leurs valeurs entières.

L' +opérateur convertit le unsigned charretourné par ces fonctions en une promotionint par nombre 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()).

Un mec programmeur
la source
37

+est là pour transformer le unsigned charen un 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 vous assurer que vous voyez une valeur numérique au lieu d'un caractère (semi-) aléatoire qui operator <<s'imprimerait avec un type de caractère.

Conteur - Unslander Monica
la source
18

Juste pour ajouter une référence aux réponses déjà données. À partir du projet de travail standard N4713 du CPP :

8.5.2.1 Opérateurs unaires
...

  1. L'opérande de l'opérateur unaire + doit être de type arithmétique, énumération non cadrée ou pointeur et le résultat est la valeur de l'argument. La promotion intégrale est effectuée sur des opérandes intégraux ou d'énumération. Le type du résultat est le type de l'opérande promu.

Et char, short, intet longsont des types intégrés.

PW
la source
12

Sans +le résultat sera différent. L'extrait de code suivant sort a 97au lieu dea a

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

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

Les arguments de caractères et de chaînes de caractères (par exemple, de type charou const char*) sont gérés par les surcharges non membres de operator<<. Tenter de sortir un caractère en utilisant la syntaxe d'appel de fonction membre (par exemple, std::cout.operator<<('c');) appellera l'une des surcharges (2-4) et affichera 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 appellera overload (7) et affichera la valeur du pointeur à la place.

La surcharge non-membre qui sera appelée lorsque vous passez une charvariable est

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

qui imprime le caractère au codet ch

Donc, fondamentalement, si vous passez char, signed charou unsigned chardirectement au flux, cela imprimera le personnage. Si vous essayez de supprimer le +sur les 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 à la place de leurs valeurs numériques , vous devez appeler la surcharge short, int, longou long long. Le moyen le plus simple de le faire est de promouvoir de charà intavec plus unaire +. C'est l'une des rares applications utiles de l' opérateur unaire plus . Un casting explicite intfonctionnera également

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

phuclv
la source
1
Vouliez-vous dire plus unaire , pas moins?
Ruslan le