15

显然char,默认情况下,plain 有可能是有符号或无符号的。Stroustrup 写道:

普通字符被认为是有符号还是无符号是实现定义的。这为一些令人讨厌的惊喜和实现依赖性打开了可能性。

如何检查我的字符是已签名还是未签名?我可能想将它们转换为int以后,我不希望它们是负面的。我应该始终unsigned char明确使用吗?

4

5 回答 5

27

从标题<limits>

std::numeric_limits<char>::is_signed

http://en.cppreference.com/w/cpp/types/numeric_limits/is_signed

于 2013-08-14T00:18:56.343 回答
18

一些替代方案:

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。)

于 2013-08-14T00:20:06.007 回答
0

使用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可以很容易地用一些iostreamfstream类型的功能替换,它通常具有unsigned charchar.

但是,如果您使用><超过 127 的字符,那么您将需要使用unsigned char(或其他一些解决方案,例如转换为int和屏蔽低 8 位)。尽量避免直接比较可能会更好(特别是在涉及非 ASCII 字符时——它们无论如何都是混乱的,因为根据语言环境、字符编码等通常有几种变体)。然而,比较平等应该有效。

于 2013-08-14T00:23:56.833 回答
0

是的,如果你想使用一个char类型并且你总是希望它是无符号的,使用unsigned char. 请注意,与其他基本整数类型不同,它与-- 即使在无符号系统上也是unsigned char不同的类型。此外,从to的转换应该是无损的,因此如果您的结果不正确,您的源值也可能不正确。charcharcharint char

测试是否是无符号的最简洁的方法char取决于您是否需要将其作为预处理器测试以及您所针对的 C++ 版本。

要使用预处理器测试有条件地编译代码, 的值CHAR_MIN应该起作用:

#include <climits>

#if (CHAR_MIN==0)
// code that relies on char being unsigned
#endif

在 C++17 中,我会使用std::is_signed_vand 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_signedstd::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 的解决方案是一个不错的选择。

于 2017-11-11T15:46:11.213 回答
-1

您可以使用预处理器命令:

 #define is_type_signed(my_type) (((my_type)-1) < 0)
于 2013-08-14T00:20:53.697 回答