显然,默认情况下,普通char
可能有签名或无签名。 Stroustrup写道:
实现定义了普通字符是被认为是有符号还是无符号。这打开了 一些令人讨厌的惊喜和实现依赖的可能性。
如何检查我的字符是签名还是未签名?我可能希望稍后将它们转换为int
,我不希望它们为负数。我应该始终明确使用unsigned char
吗?
答案 0 :(得分:24)
来自标题<limits>
std::numeric_limits<char>::is_signed
http://en.cppreference.com/w/cpp/types/numeric_limits/is_signed
答案 1 :(得分:15)
一些替代方案:
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&#39; -fsigned-char
和-funsigned-char
。
std::numeric_limits<char>::is_signed
,Benjamin Lindley's answer建议,可能会更清楚地表达意图。
(另一方面,我建议的方法也可以应用于C.)
答案 2 :(得分:0)
使用unsigned char
“总是”可以给你一些有趣的惊喜,因为大多数C风格的函数,如printf
,fopen
,将使用char
,而不是{ {1}}。
编辑:带有C风格功能的“趣味”示例:
unsigned char
会出错(事实上,我为const unsigned char *cmd = "grep -r blah *.txt";
FILE *pf = popen(cmd, "r");
行提供了一个,而*cmd =
行有一个错误)。使用popen
将正常工作。我选择了const char *cmd = ...
,因为它是一个用一些标准C ++功能取代并不容易的函数 - 显然,popen
或printf
很容易被一些fopen
替换或者iostream
类型功能,通常包含fstream
和unsigned char
的替代方案。
但是,如果您对超过127的字符使用char
或>
,则需要使用<
(或其他一些解决方案,例如转换为{{ 1}}并屏蔽低8位)。尝试避免直接比较可能更好(特别是当涉及非ASCII字符时 - 无论如何它们都很混乱,因为通常有几种变体取决于区域设置,字符编码等)。然而,比较平等应该是有效的。
答案 3 :(得分:0)
是的,如果您想使用char
类型并且始终希望它是未签名的,请使用unsigned char
。请注意,与其他基本整数类型不同,unsigned char
与char
的类型不同 - 即使在char
未签名的系统上也是如此。此外,从char
转换为int
ought to be lossless,如果结果不正确,您的来源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
和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的解决方案是一个很好的选择。
答案 4 :(得分:-1)
您可以使用预处理器命令:
#define is_type_signed(my_type) (((my_type)-1) < 0)