例如,
#include <iostream>
int main() {
unsigned n{};
std::cin >> n;
std::cout << n << ' ' << (bool)std::cin << std::endl;
}
输入-1
时,clang 6.0.0输出 0 0
而 gcc 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 toerr
.
请注意,所有这些都是关于“要转换的字段”,而不是 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 toerr
.
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/