Qual é o objetivo de um "+" unário antes de uma chamada para membros std :: numeric_limits <char não assinado>?

130

Eu vi esse exemplo na documentação da cppreference parastd::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';
}

Eu não entendo o operador "+" em

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

Eu testei, substituí-o por "-", e isso também funcionou. Para que serve um operador "+"?

Zhang
fonte
3
Tente. O que você ganha se deixar de fora o +?
Pete Becker
4
Esta questão não precisa ser autor da questão se o escritor dos cuidados de código para explicar o que significa ou usar uma conversão explícita em vez ...
user202729
se você substituir com -, em seguida, as saídas não serão os valores corretos para os limites
phuclv
1
Para que conste, se você deseja pesquisar esse tipo de coisa no Google, isso é chamado de operador "mais unário" - é unário porque leva um único valor (nesse caso, a coisa logo a seguir) e "plus "é a maneira mais amigável de dizer o Google +. Nesse caso, sua consulta provavelmente seria "c ++ unary plus". É ... não exatamente intuitivo, e você ainda precisa aprender a ler a documentação que encontrará, mas na IMO é uma habilidade útil de cultivar.
Fund Monica's Lawsuit

Respostas:

137

O operador de saída <<ao receber um charsinal (assinado ou não) o escreverá como um caractere .

Aqueles função retornará valores do tipo unsigned char. E, como observado acima, isso imprimirá os caracteres que esses valores representam na codificação atual, não seus valores inteiros.

Os +convertidos operador a unsigned charretornado por essas funções de um intmeio de promoção inteiro . O que significa que os valores inteiros serão impressos.

Uma expressão como +std::numeric_limits<unsigned char>::lowest()é essencialmente igual a static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

Algum cara programador
fonte
37

+existe para transformar o unsigned charem um int. O +operador preserva o valor, mas tem o efeito de induzir promoção integral em seu operando. É para garantir que você veja um valor numérico em vez de algum caractere (semi-) aleatório que operator <<seria impresso quando receber um tipo de caractere.

Contador de histórias - Unslander Monica
fonte
18

Apenas para adicionar uma referência às respostas já dadas. A partir do esboço de trabalho padrão do CPP N4713 :

8.5.2.1 Operadores unários
...

  1. O operando do operador unário + deve ter aritmética, enumeração sem escopo ou tipo de ponteiro, e o resultado é o valor do argumento. A promoção integral é realizada em operandos integrais ou de enumeração. O tipo do resultado é o tipo do operando promovido.

E char, short, int, e longsão tipos integrais.

PW
fonte
12

Sem +o resultado será diferente. O seguinte fragmento gera em a 97vez dea a

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

O motivo é que diferentes sobrecargas imprimem diferentes tipos de dados . Não há basic_ostream& operator<<( char value );sobrecarga std::basic_ostreame é explicado no final da página

Os argumentos de caractere e sequência de caracteres (por exemplo, do tipo charou const char*) são tratados pelas sobrecargas de não membros de operator<<. Tentar gerar um caractere usando a sintaxe de chamada da função de membro (por exemplo, std::cout.operator<<('c');) chamará uma das sobrecargas (2-4) e produzirá o valor numérico . Tentar gerar uma cadeia de caracteres usando a sintaxe da chamada da função de membro chamará sobrecarga (7) e imprimirá o valor do ponteiro.

A sobrecarga de não membro que será chamada quando você passar uma charvariável é

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

que imprime o caractere no ponto de código ch

Então, basicamente, se você passar char, signed charou unsigned chardiretamente para o fluxo, o personagem será impresso. Se você tentar remover as +linhas acima, verá que ele imprime alguns caracteres "estranhos" ou não visíveis, o que não é o que se espera

Se você quiser seus valores numéricos, em vez você deve chamar a sobrecarga para short, int, longou long long. A maneira mais fácil de fazer isso é promovendo de charpara intcom mais unário +. Essa é uma das raras aplicações úteis do operador unary plus . Um elenco explícito para inttambém funcionará

Muitas pessoas enfrentaram esse problema no SO, como

phuclv
fonte
1
Você quis dizer unário mais , não menos?
Ruslan