显然char
,默认情况下,plain 有可能是有符号或无符号的。Stroustrup 写道:
普通字符被认为是有符号还是无符号是实现定义的。这为一些令人讨厌的惊喜和实现依赖性打开了可能性。
如何检查我的字符是已签名还是未签名?我可能想将它们转换为int
以后,我不希望它们是负面的。我应该始终unsigned char
明确使用吗?
从标题<limits>
std::numeric_limits<char>::is_signed
http://en.cppreference.com/w/cpp/types/numeric_limits/is_signed
一些替代方案:
const bool char_is_signed = (char)-1 < 0;
#include <climits>
const bool char_is_signed = CHAR_MIN < 0;
是的,有些系统确实将普通char
类型设为无符号类型。我遇到的例子:Cray T90、Cray SV1、Cray T3E、SGI MIPS IRIX、IBM PowerPC AIX。并且任何使用 EBCDIC 的系统几乎都必须制作普通的char
无符号字符,以便所有基本字符都具有非负值。(有些编译器可以选择控制 的符号char
,例如 gcc-fsigned-char
和-funsigned-char
.)
但是std::numeric_limits<char>::is_signed
,正如本杰明林德利的回答所暗示的那样,可能更清楚地表达了意图。
(另一方面,我建议的方法也可以应用于 C。)
使用unsigned char
“always”可能会给您带来一些有趣的惊喜,因为大多数 C 风格的函数,如printf
, fopen
, 将使用char
, not unsigned char
。
编辑:具有 C 风格函数的“有趣”示例:
const unsigned char *cmd = "grep -r blah *.txt";
FILE *pf = popen(cmd, "r");
将给出错误(事实上,我得到一个错误的*cmd =
线路,一个错误的popen
线路)。使用const char *cmd = ...
将正常工作。我之所以选择popen
它,是因为它是一个用一些标准 C++ 功能替换的函数——显然,printf
或者fopen
可以很容易地用一些iostream
或fstream
类型的功能替换,它通常具有unsigned char
与char
.
但是,如果您使用>
或<
超过 127 的字符,那么您将需要使用unsigned char
(或其他一些解决方案,例如转换为int
和屏蔽低 8 位)。尽量避免直接比较可能会更好(特别是在涉及非 ASCII 字符时——它们无论如何都是混乱的,因为根据语言环境、字符编码等通常有几种变体)。然而,比较平等应该有效。
是的,如果你想使用一个char
类型并且你总是希望它是无符号的,使用unsigned char
. 请注意,与其他基本整数类型不同,它与-- 即使在无符号系统上也是unsigned char
不同的类型。此外,从to的转换应该是无损的,因此如果您的结果不正确,您的源值也可能不正确。char
char
char
int
char
测试是否是无符号的最简洁的方法char
取决于您是否需要将其作为预处理器测试以及您所针对的 C++ 版本。
要使用预处理器测试有条件地编译代码, 的值CHAR_MIN
应该起作用:
#include <climits>
#if (CHAR_MIN==0)
// code that relies on char being unsigned
#endif
在 C++17 中,我会使用std::is_signed_v
and std::is_unsigned_v
:
#include <type_traits>
static_assert(std::is_unsigned_v<char>);
// code that relies on char being unsigned
如果您针对 C++11 或 C++14 编写,则需要稍微冗长的std::is_signed
和std::is_unsigned
:
#include <type_traits>
static_assert(std::is_unsigned<char>::value, "char is signed");
// code that relies on char being unsigned
对于 C++ 的所有修订版,@benjamin-lindley 的解决方案是一个不错的选择。
您可以使用预处理器命令:
#define is_type_signed(my_type) (((my_type)-1) < 0)