在调用 std::numeric_limits<unsigned char> 成员之前,一元“+”的目的是啥?

Posted

技术标签:

【中文标题】在调用 std::numeric_limits<unsigned char> 成员之前,一元“+”的目的是啥?【英文标题】:What is the purpose of a unary "+" before a call to std::numeric_limits<unsigned char> members?在调用 std::numeric_limits<unsigned char> 成员之前,一元“+”的目的是什么? 【发布时间】:2019-02-08 07:06:34 【问题描述】:

我看到this example in cppreference's documentation for 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';

我不明白

中的“+”运算符
<< +std::numeric_limits<unsigned char>::lowest()

我已经测试过了,用“-”替换它,这也有效。 这样的“+”运算符有什么用?

【问题讨论】:

试试看。如果省略+,你会得到什么? 如果代码的编写者愿意解释它的含义或使用显式强制转换,那么这个问题将不需要来询问... 如果您替换为 -,则输出将不是限制的正确值 为了记录,如果你想自己谷歌这种东西,这被称为“一元加号”运算符——它是一元的,因为它需要一个值(在这种情况下,东西紧随其后),并且“加号”是 Google 友好的表示 + 的方式。在这种情况下,您的查询可能是“c++ unary plus”。它......不是很直观,你仍然需要学习阅读你会找到的文档,但 IMO 这是一项有用的技能,可以培养。 【参考方案1】:

输出运算符&lt;&lt; 在传递char(有符号或无符号)时会将其写为字符

这些函数将返回unsigned char 类型的值。并且如上所述,它将打印这些值在当前编码中表示的字符,而不是它们的整数值。

+ 运算符将这些函数返回的unsigned char 转换为intinteger promotion。这意味着将打印整数值。

+std::numeric_limits&lt;unsigned char&gt;::lowest() 这样的表达式本质上等于static_cast&lt;int&gt;(std::numeric_limits&lt;unsigned char&gt;::lowest())

【讨论】:

【参考方案2】:

+ 可以将unsigned char 变成int+ 运算符是保值的,但它具有在其操作数上诱导积分提升的效果。这是为了确保您看到的是一个数值,而不是operator &lt;&lt; 在给定字符类型时会打印的一些(半)随机字符。

【讨论】:

【参考方案3】:

只是为了添加对已经给出的答案的参考。来自CPP标准工作草案N4713:

8.5.2.1 一元运算符 ...

    一元 + 运算符的操作数应具有算术、无范围枚举或指针类型,结果是参数的值。 对整数或枚举操作数执行整数提升。结果的类型是提升的操作数的类型。

charshortintlong 是整数类型。

【讨论】:

【参考方案4】:

没有+,结果会有所不同。以下 sn -p 输出 a 97 而不是 a a

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

原因是不同的重载打印不同类型的数据std::basic_ostream 没有 basic_ostream&amp; operator&lt;&lt;( char value ); 重载,页面末尾有说明

字符和字符串参数(例如,charconst char* 类型)由 operator&lt;&lt; 的 non-member overloads 处理。尝试使用成员函数调用语法(例如,std::cout.operator&lt;&lt;('c');)输出字符将调用重载之一(2-4)并输出数值。尝试使用成员函数调用语法输出字符串将调用重载 (7) 并打印指针值。

传递char 变量时将调用的non-member overload 是

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

打印出代码点ch处的字符

所以基本上如果你将charsigned charunsigned char 直接传递给流,它会打印出字符。如果您尝试删除上述行中的+,您会看到它会打印一些“奇怪”或不可见的字符,这不是人们所期望的

如果您想要它们的数值,则必须调用 shortintlonglong long 的重载。最简单的方法是从char 升级到int,一元加+。这是unary plus operator 中的rare useful applications 之一。对int 的显式转换也可以使用

有很多人在 SO 上遇到过这个问题

cout not printing unsigned char std::cout deal with uint8_t as a character uint8_t can't be printed with cout

【讨论】:

你的意思是一元,而不是减吗?

以上是关于在调用 std::numeric_limits<unsigned char> 成员之前,一元“+”的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

2019/11/7

C++/C++11中std::numeric_limits的使用

val != std::numeric_limits<double>::infinity() 或 !isinf(val) 或 isfinite(val)

在 C++ 中使用 NaN?

static_cast<T>(-1) 是在没有 numeric_limits 的情况下生成全一位数据的正确方法吗?

使用 epsilon 将双精度数与零进行比较