是否可以保证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)?
问题描述
问题如何正确使用 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] :
-
对于每个
int
值e
,to_char_type(e)
返回-
c
,如果eq_int_type(e,to_int_type(c))
对于某些c
; -
其他一些未指定的值.
-
-
对于每对
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()
xorf == eof()
; -
未指定.
-
-
eof()
返回一个值e
,使得所有!eq_int_type(e,to_int_type(c))
> c . -
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
的转换是双射的.
现在让我们验证需求:
-
对于每个
int
值e
,如果某些的
,然后是eq_int_type(e,to_int_type(c))
ce == int(c)+ 1
.因此,to_char_type(e)== char(int(c))== c
. -
对于每对
int
值e
和f
,如果e == to_int_type(c)
和f == to_int_type(d)
用于某些c
和d
,然后是eq_int_type(e,f)
iffint(c)+ 1 == int(d)+1
iffc == d
(根据属性1).EOF案例也很容易验证. -
对于每个
char
值c
,int(c)> = -128
,因此int(c)+ 1!= EOF
.因此,!eq_int_type(eof(),to_int_type(c))
. -
对于每对
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]:
For every
int
valuee
,to_char_type(e)
returnsc
, ifeq_int_type(e, to_int_type(c))
for somec
;some unspecified value otherwise.
For every pair of
int
valuese
andf
,eq_int_type(e, f)
returnseq(c, d)
, ife == to_int_type(c)
andf == to_int_type(d)
for somec
andd
;true
, ife == eof()
andf == eof()
;false
, ife == eof()
xorf == eof()
;unspecified otherwise.
eof()
returns a valuee
such that!eq_int_type(e, to_int_type(c))
for allc
.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
toint
is value-preserving;(property 2) the conversion from
char
tounsigned char
is bijective.
Now let's verify the requirements:
For every
int
valuee
, ifeq_int_type(e, to_int_type(c))
for somec
, thene == int(c) + 1
. Therefore,to_char_type(e) == char(int(c)) == c
.For every pair of
int
valuese
andf
, ife == to_int_type(c)
andf == to_int_type(d)
for somec
andd
, theneq_int_type(e, f)
iffint(c) + 1 == int(d) + 1
iffc == d
(by property 1). The EOF cases are also trivially verifiable.For every
char
valuec
,int(c) >= -128
, soint(c) + 1 != EOF
. Therefore,!eq_int_type(eof(), to_int_type(c))
.For every pair of
char
valuesc
andd
,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< char> :: to_int_type(c)== static_cast< int>(c)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!