微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否保证 std::char_traits<char>::to_int_type(c) == static_cast<int>(c)?

如何解决是否保证 std::char_traits<char>::to_int_type(c) == static_cast<int>(c)?

问题How to use correctly the return value from std::cin.get() and std::cin.peek()?让我怀疑是否可以保证

std::char_traits<char>::to_int_type(c) == static_cast<int>(c)

对于所有有效的 charc


这出现在很多地方。例如,istream::peek 调用 streambuf::sgetc,它使用 to_int_typechar 值转换为 int_type。现在,std::cin.peek() == '\n' 真的意味着下一个字符是 \n 吗?


这是我的分析。让我们从 [char.traits.require][char.traits.specializations.char] 收集碎片:

  1. 对于每个 inteto_char_type(e) 返回

    • c,如果 ​eq_­int_­type(e,​to_­int_­type(c)) 对于某些 c;

    • 其他一些未指定的值。

  2. 对于每对 intefeq_­int_­type(e,f) 返回

    • eq(c,d),if e == to_int_type(c) and f == to_int_type(d) for some c and d;

    • true,如果 e == eof()f == eof();

    • false,if e == eof() xor f == eof();

    • 未指定。

  3. eof() 返回一个e,使得所有 !eq_int_type(e,to_int_type(c))c

  4. eq(c,d) 仅当 (unsigned char) c == (unsigned char) d

现在,考虑这个假设的实现:(语法简化)

//          char: [-128,127]
// unsigned char: [0,255]
//           int: [-2^31,2^31-1]

#define EOF INT_MIN

char to_char_type(int e) {
    return char(e - 1);
}

int to_int_type(char c) {
    return int(c) + 1;
}

bool eq(char c,char d) {
    return c == d;
}

bool eq_int_type(int c,int d) {
    return c == d;
}

int eof() {
    return EOF;
}

注意

  • (性质 1)从 unsigned charint 的转换是保值的;

  • (性质 2)从 charunsigned char 的转换是双射的。

现在让我们验证需求:

  1. 对于每一个 inte,如果 ​eq_­int_­type(e,​to_­int_­type(c)) 代表某个 c,那么 e == int(c) + 1。因此,to_char_type(e) == char(int(c)) == c

  2. 对于每对intef,如果e == to_int_type(c)f == to_int_type(d)对于某些c和{{ 1}},然后 d iff eq_int_type(e,f) iff int(c) + 1 == int(d) + 1(根据属性 1)。 EOF 案例也很容易验证。

  3. 对于每个 c == dcharc,所以 int(c) >= -128。因此,int(c) + 1 != EOF

  4. 对于每对 !eq_int_type(eof(),to_int_type(c))charcd iff eq(c,d)(根据属性 2)。

这是否意味着这个实现是一致的,因此 (unsigned char) c == (unsigned char d) 没有做它应该做的事情?我的分析中是否遗漏了什么?

解决方法

这是否意味着这个实现是一致的,因此 std::cin.peek() == '\n' 没有做它应该做的事情?

我同意你的分析。这不能保证。

看来您必须使用 eq_­int_­type(std::cin.peek(),​to_­int_­type('\n')) 来保证正确的结果。


附言由于 ​to_­char_­type(EOF) 中的签名溢出,您的 INT_MIN - 1 具有未定义的行为。当然,在这种情况下未指定该值,但您仍然不能拥有 UB。这将是有效的:

char to_char_type(int e) {
    return e == EOF
         ? 0 // doesn't matter
         : char(e - 1);
}

to_int_type 将在 int 和 char 大小相同的系统上使用 UB,以防万一c == INT_MAX,但您已经排除了那些具有假设大小的系统。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。