c++ - 是否应该通过 std::cin 将负数读入 unsigned 失败(gcc,clang 不同意)?

标签 c++ language-lawyer c++17 cin c++-standard-library

例如,

#include <iostream>

int main() {
  unsigned n{};
  std::cin >> n;
  std::cout << n << ' ' << (bool)std::cin << std::endl;
}

输入-1时,clang 6.0.0输出 0 0gcc 7.2.0输出 4294967295 1。我想知道谁是正确的。或者也许两者都是正确的标准没有指定这一点?如果失败,我的意思是 (bool)std::cin 被评估为假。 clang 6.0.0 也无法输入 -0


从 Clang 9.0.0 和 GCC 9.2.0 开始,在 Clang 的情况下使用 libstdc++ 或 libc++ 的两个编译器都同意上述程序的结果,与 C++ 版本无关 (>= C++11 ) 使用并打印

4294967295 1

即他们将值设置为 ULLONG_MAX 并且没有在流上设置故障位。

最佳答案

我认为在 C++171 中两者都是错误的,预期的输出应该是:

4294967295 0

虽然返回的值对于两个编译器的最新版本都是正确的,但我认为 ios_­base​::​failbit应该设置,但我也认为标准中要转换的字段的概念存在混淆,这可能会解释当前的行为。

标准说——[facet.num.get.virtuals#3.3] :

The sequence of chars accumulated in stage 2 (the field) is converted to a numeric value by the rules of one of the functions declared in the header <cstdlib>:

  • For a signed integer value, the function strtoll.

  • For an unsigned integer value, the function strtoull.

  • For a floating-point value, the function strtold.

所以我们退回到 std::strtoull ,必须返回2 ULLONG_MAX 并且未设置 errno在这种情况下(这是两个编译器所做的)。

但在同一 block 中(强调是我的):

The numeric value to be stored can be one of:

  • zero, if the conversion function does not convert the entire field.

  • the most positive (or negative) representable value, if the field to be converted to a signed integer type represents a value too large positive (or negative) to be represented in val.

  • the most positive representable value, if the field to be converted to an unsigned integer type represents a value that cannot be represented in val.

  • the converted value, otherwise.

The resultant numeric value is stored in val. If the conversion function does not convert the entire field, or if the field represents a value outside the range of representable values, ios_­base​::​failbit is assigned to err.

请注意,所有这些都是关于“要转换的字段”,而不是 std::strtoull 返回的实际值。 .这里的字段实际上是字符'-', '1'的加宽序列.

由于该字段表示的值 (-1) 不能用 unsigned 表示,返回值应为 UINT_MAX并且故障位应设置为 std::cin .


1 clang实际上在 C++17 之前是正确的,因为上面引用中的第三个项目符号是:

- the most negative representable value or zero for an unsigned integer type, if the field represents a value too large negative to be represented in val. ios_base::failbit is assigned to err.

2 std::strtoull 返回 ULLONG_MAX因为(感谢@NathanOliver)- C/7.22.1.4.5:

If the subject sequence has the expected form and the value of base is zero, the sequence of characters starting with the first digit is interpreted as an integer constant according to the rules of 6.4.4.1. [...] If the subject sequence begins with a minus sign, the value resulting from the conversion is negated (in the return type).

关于c++ - 是否应该通过 std::cin 将负数读入 unsigned 失败(gcc,clang 不同意)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49921271/

相关文章:

c++ - 函数属性 returns_twice

java - 公共(public)类加载器加载库时无法调用 JNI 方法

c++ - "using namespace"用于定义全局函数

c++ - 完美转发const ref扣减错误

c++ - 模板、静态和 dll

c++ - g++ 和 clang++ 具有完整模板参数的不同行为

c++ - 如何从本地套接字创建 Boost.Asio 套接字?

c++ - 可以在尾随返回类型语法中直接使用参数值(不是它的类型而是值本身)

c - 指向结构指针的指针是否具有隐含的可互换性?

c++ - 如果没有显式限定名称,如何调用纯虚函数?