将int与char进行比较时,我应该显式地转换其中一个,还是让编译器为我做?有关系吗?为什么呢?
E.g。
int i = 113;
char c = 'q';
if (static_cast<char>(i) == c)
cout << "equal";
// OR
if (i == c)
cout << "equal";
答案 0 :(得分:6)
实际上,由于integral promotion在某些情况下确实很重要,而int
到char
的显式转换会截断更高的字节。
基本上,如果您尝试比较两种不同大小的数字类型,则会有一些规则可以将它们转换为某些常见类型&#34;,这通常足以适应&#34; #34;两种类型。但是如果你进行了明确的转换,你可能会丢失一些信息。
请考虑以下代码:
#include <iostream>
using namespace std;
int main() {
int i = 113;
char c = 'q';
cout << (static_cast<char>(i) == c) << endl; // 1
cout << (i == c) << endl; // 1
i += 0x100; // i is now 369, but lower byte is 113.
cout << (static_cast<char>(i) == c) << endl; // 1
cout << (i == c) << endl; // 0
return 0;
}
当您明确地将int
转换为char
时,较高字节通常会被截断(如评论中所述,它是实现定义的)。但是,当您将int
与char
进行比较时,后者会自动提升为int
,然后会比较两个ints
。
在这种特殊情况下,您可以避免显式转换。但是,如this answer中所述,这样做并不总是在意识形态上正确,因为int
中存储的标准库字符通常是非负数(例如0..255
) ,而不是char
,可以根据编译器/平台进行签名(例如-128..127
)。如果您的比较中存在非ASCII字符,则会导致潜在问题。
因此,如果您绝对确定永远不需要非ASCII,则可以避免显式转换。但如果不是这种情况(或者你想养成一个好习惯),那么在与{char
进行比较之前,最好先考虑约定并将unsigned char
转换为int
。 1}}:
i == static_cast<unsigned char>(c)
答案 1 :(得分:1)
您的示例中的演员应该采用另一种方式,从char
到int
,通过 unsigned char
。
将char
值表示为int
的既定非常强大的约定,特别是isalpha
等函数,表示负char
值表示为值转换为unsigned char
,严格来说是非负值。
对于遵守这一最常见惯例的代码,
中的条件if (static_cast<char>(i) == c)
完全是错误的。
例如,对于8位字节和2位补码签名char
类型,这是迄今为止最常见的类型,i
值128代表char
值-128。上面的条件可能会错误地产生false
,因为当值不适合于已转换为有符号的类型时,您具有实现定义的行为。然后演员完全不必要地引入了一个bug。
正确的条件是将char
提升为int
,通过将负值转换为严格非负值的绕道:
using Byte = unsigned char;
//...
if( i == static_cast<Byte>( c ) )
如果sizeof(int)
= 1,即使char
为无符号类型,此条件仍然有效。
标准库的char
分类函数对于负参数具有未定义的行为,但特殊值EOF
除外。
所以电话
isalpha( c )
通常会有未定义的行为,因为通常char
是签名类型,并且可能会出现负值,例如拉丁语1编码为'Å'
。
应该是
using Byte = unsigned char;
//...
isalpha( static_cast<Byte>( c ) )
答案 2 :(得分:-2)
答案是......这取决于你正在使用的“char”和“int”的范围......