![](/img/trans.png)
[英]Why do arithmetic operations on unsigned chars promote them to signed integers?
[英]How to check if plain chars are signed or unsigned?
显然,默认情况下有可能将纯char
签名或不签名。 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
。)
但是,正如本杰明·林德利 ( Benjamin Lindley)的答案所建议的std::numeric_limits<char>::is_signed
, std::numeric_limits<char>::is_signed
可能更清楚地表达了意图。
(另一方面,我建议的方法也可以应用于C。)
始终使用unsigned char
可能会给您带来一些有趣的惊喜,因为大多数C样式函数(如printf
, fopen
)将使用char
,而不是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
是从不同类型的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
和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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.