如果我在与char进行比较之前没有明确地将int转换为char,这是否重要?

时间:2017-02-03 06:32:57

标签: c++

将int与char进行比较时,我应该显式地转换其中一个,还是让编译器为我做?有关系吗?为什么呢?

E.g。

int i = 113;
char c = 'q';
if (static_cast<char>(i) == c)
    cout << "equal";
// OR
if (i == c)
    cout << "equal";

3 个答案:

答案 0 :(得分:6)

实际上,由于integral promotion在某些情况下确实很重要,而intchar的显式转换会截断更高的字节。 基本上,如果您尝试比较两种不同大小的数字类型,则会有一些规则可以将它们转换为某些常见类型&#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时,较高字节通常会被截断(如评论中所述,它是实现定义的)。但是,当您将intchar进行比较时,后者会自动提升为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)

您的示例中的演员应该采用另一种方式,从charint通过 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)

  • int的大小为 4字节
  • char的大小为 2个字节

答案是......这取决于你正在使用的“char”和“int”的范围......