是否可以保证std :: char_traits< char> :: to_int_type(c)== static_cast< int>(c)? [英] Is it guaranteed that std::char_traits<char>::to_int_type(c) == static_cast<int>(c)?

查看:64
本文介绍了是否可以保证std :: char_traits< char> :: to_int_type(c)== static_cast< int>(c)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题如何正确使用 std :: cin.get() std :: cin.peek()?让我想知道是否可以保证

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

对于所有有效的 char c .


很多地方都会出现这种情况.例如, istream :: peek 调用 streambuf :: sgetc ,该代码使用 to_int_type char 值转换为 int_type .现在, std :: cin.peek()=='\ n'真的意味着下一个字符是 \ n 吗?


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

  1. 对于每个 int e to_char_type(e)返回

    • c ,如果 eq_int_type(e,to_int_type(c))对于某些 c ;

    • 其他一些未指定的值.

  2. 对于每对 int e f eq_int_type(e,f)返回

    • eq(c,d),如果 e == to_int_type(c) f == to_int_type(d)对于某些 c d ;

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

    • false ,如果 e == eof() xor f == eof();

    • 未指定.

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

  4. eq(c,d) iff (unsigned char)c ==(unsigned char)d .

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

 <代码>//char:[-128,127]//无符号字符:[0,255]//int:[-2 ^ 31、2 ^ 31-1]#定义EOF INT_MINchar to_char_type(int e){返回char(e-1);}int to_int_type(char c){返回int(c)+ 1;}bool eq(char c,char d){返回c == d;}bool eq_int_type(int c,int d){返回c == d;}int eof(){返回EOF;} 

请注意

  • (属性1)从 unsigned char int 的转换是保值的;

  • (属性2)从 char unsigned char 的转换是双射的.

现在让我们验证需求:

  1. 对于每个 int e ,如果某些 eq_int_type(e,to_int_type(c))c ,然后是 e == int(c)+ 1 .因此, to_char_type(e)== char(int(c))== c .

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

  3. 对于每个 char c int(c)> = -128 ,因此 int(c)+ 1!= EOF .因此,!eq_int_type(eof(),to_int_type(c)).

  4. 对于每对 char c d eq(c,d)iff (unsigned char)c ==(unsigned char d)(根据属性2).

这是否意味着该实现是符合标准的,因此 std :: cin.peek()=='\ n'并未执行应做的事情?我错过了分析中的任何内容吗?

解决方案

这是否意味着该实现是符合标准的,因此std :: cin.peek()=='\ n'并未执行应做的事情?

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

看来您必须使用 eq_int_type(std :: cin.peek(),to_int_type('\ n'))来保证正确的结果.


P.S.由于 INT_MIN-1 中的签名溢出,您的 to_char_type(EOF)具有未定义的行为.当然,在这种情况下,该值未指定,但是您仍然不能拥有UB.这将是有效的:

  char to_char_type(int e){返回e == EOF?0//没关系:char(e-1);} 

c == INT_MAX 的情况下,

to_int_type 在int和char大小相同的系统上将具有UB,但是您已排除了那些假设大小的系统./p>

The question How to use correctly the return value from std::cin.get() and std::cin.peek()? made me wonder if it is guaranteed that

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

for all valid char values c.


This comes up in a lot of places. For example, istream::peek calls streambuf::sgetc, which uses to_int_type to convert the char value into int_type. Now, does std::cin.peek() == '\n' really mean that the next character is \n?


Here's my analysis. Let's collect the pieces from [char.traits.require] and [char.traits.specializations.char]:

  1. For every int value e, to_char_type(e) returns

    • c, if ​eq_­int_­type(e, ​to_­int_­type(c)) for some c;

    • some unspecified value otherwise.

  2. For every pair of int values e and f, eq_­int_­type(e, f) returns

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

    • true, if e == eof() and f == eof();

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

    • unspecified otherwise.

  3. eof() returns a value e such that !eq_int_type(e, to_int_type(c)) for all c.

  4. eq(c, d) iff (unsigned char) c == (unsigned char) d.

Now, consider this hypothetical implementation: (syntactically simplified)

//          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;
}

Note that

  • (property 1) the conversion from unsigned char to int is value-preserving;

  • (property 2) the conversion from char to unsigned char is bijective.

Now let's verify the requirements:

  1. For every int value e, if ​eq_­int_­type(e, ​to_­int_­type(c)) for some c, then e == int(c) + 1. Therefore, to_char_type(e) == char(int(c)) == c.

  2. For every pair of int values e and f, if e == to_int_type(c) and f == to_int_type(d) for some c and d, then eq_int_type(e, f) iff int(c) + 1 == int(d) + 1 iff c == d (by property 1). The EOF cases are also trivially verifiable.

  3. For every char value c, int(c) >= -128, so int(c) + 1 != EOF. Therefore, !eq_int_type(eof(), to_int_type(c)).

  4. For every pair of char values c and d, eq(c, d) iff (unsigned char) c == (unsigned char d) (by property 2).

Does that mean this implementation is conforming, and therefore std::cin.peek() == '\n' does not do what it is supposed to do? Did I miss anything in my analysis?

解决方案

Does that mean this implementation is conforming, and therefore std::cin.peek() == '\n' does not do what it is supposed to do?

I agree with your analysis. This isn't guaranteed.

It appears that you would have to use eq_­int_­type(std::cin.peek(), ​to_­int_­type('\n')) to guarantee correct result.


P.S. Your ​to_­char_­type(EOF) has undefined behaviour due to signed overflow in INT_MIN - 1. Sure, the value is unspecified in this case, but you still cannot have UB. This would be valid:

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

to_int_type would have UB on systems where int and char are same size in case c == INT_MAX, but you've excluded those systems with the hypothetical sizes.

这篇关于是否可以保证std :: char_traits&lt; char&gt; :: to_int_type(c)== static_cast&lt; int&gt;(c)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆