如果我在与字符进行比较之前没有明确将 int 转换为字符,这有关系吗?
Does it matter if I don't explicitly cast an int to a char before comparison with a char?
在比较 int 和 char 时,我应该显式转换其中一个,还是让编译器为我做?有关系吗?为什么?
例如
int i = 113;
char c = 'q';
if (static_cast<char>(i) == c)
cout << "equal";
// OR
if (i == c)
cout << "equal";
实际上,在某些情况下,由于积分提升以及将int
显式转换为char
会截断更高的字节这一事实,它确实很重要。 基本上,如果您尝试比较两种不同大小的类似数字的类型,则可以通过某些规则将它们转换为某种"通用类型",这通常足以"适合"两种类型。但是,如果您进行显式转换,则可能会丢失一些信息。
请考虑以下代码:
#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
。
在这种特殊情况下,您可以避免显式强制转换。然而,正如这个答案中提到的,这样做在意识形态上并不总是正确的,因为在标准库中存储的字符通常是非负数int
(例如0..255
),而不是char
,可以根据编译器/平台进行签名(例如-128..127
)。如果比较中有非 ASCII 字符,这将导致潜在问题。
因此,如果您绝对确定永远不需要非 ASCII,则可以避免显式强制转换。但如果不是这种情况(或者如果你想养成一个好习惯),最好在与int
进行比较之前考虑一下约定并将char
转换为unsigned char
:
i == static_cast<unsigned char>(c)
示例中的强制转换应该通过unsigned char
从char
到int
将char
值表示为int
的非常非常强的约定,特别是对于像isalpha
这样的函数,是负char
值表示为转换为unsigned char
的值,一个严格的非负值。
对于遵守此最常见约定的代码,条件在
if (static_cast<char>(i) == c)
做完全错误的事情。
例如,对于 8 位字节和 2 的补码符号char
类型(这是迄今为止最常见的),i
值 128 表示char
值 -128。然后,上述条件可能会错误地生成false
因为当值不适合强制转换为签名类型时,您具有实现定义的行为。然后,演员阵容完全不必要地引入了一个错误。
相反,正确的条件通过绕道将负值转换为严格的非负值来将该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 ) )
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 尝试将字符串/字符转换为整数会产生意外结果
- 如何使用C++将字符串中的字符转换为整数变量
- 字符转换功能 std::isupper() & std::islower() C++17
- 将字符 * 转换为字符串 *
- 在编译时将常量字符* 转换为常量 char_type*
- 如何在 C/C++ 中将无符号字符*转换为无符号字符数组?
- 错误:请求从"常量字符 [5]"转换为非标量类型"字符串"
- 无法使用字符串流将字符转换为字符串C++
- 将无符号字符 C++ 转换为 C#
- C++:使用没有位移位的指针将无符号字符转换为无符号 int
- 为什么我可以隐式地将字符*转换为常量字符*,但不能将无符号字符*
- 无法<string>从"常量字符 []"转换为<类名>
- 不能将字符转换为整数吗?
- 编译时将字符*转换为字节
- CP1251:从字符* 转换为 wchar_t* 时的编码失真
- 将单个字符转换为 std::string 前缀 \x01
- PPM 将字符转换为 int 授予负数
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类
- 将常量字符* 转换为字符时出错