如何检查普通字符是签名还是未签名?

时间:2013-08-14 00:15:47

标签: c++ syntax char

显然,默认情况下,普通char可能有签名或无签名。 Stroustrup写道:

  

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

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

5 个答案:

答案 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_signedBenjamin Lindley's answer建议,可能会更清楚地表达意图。

(另一方面,我建议的方法也可以应用于C.)

答案 2 :(得分:0)

使用unsigned char“总是”可以给你一些有趣的惊喜,因为大多数C风格的函数,如printffopen,将使用char,而不是{ {1}}。

编辑:带有C风格功能的“趣味”示例:

unsigned char

会出错(事实上,我为const unsigned char *cmd = "grep -r blah *.txt"; FILE *pf = popen(cmd, "r"); 行提供了一个,而*cmd =行有一个错误)。使用popen将正常工作。我选择了const char *cmd = ...,因为它是一个用一些标准C ++功能取代并不容易的函数 - 显然,popenprintf很容易被一些fopen替换或者iostream类型功能,通常包含fstreamunsigned char的替代方案。

但是,如果您对超过127的字符使用char>,则需要使用<(或其他一些解决方案,例如转换为{{ 1}}并屏蔽低8位)。尝试避免直接比较可能更好(特别是当涉及非ASCII字符时 - 无论如何它们都很混乱,因为通常有几种变体取决于区域设置,字符编码等)。然而,比较平等应该是有效的。

答案 3 :(得分:0)

是的,如果您想使用char类型并且始终希望它是未签名的,请使用unsigned char。请注意,与其他基本整数类型不同,unsigned charchar的类型不同 - 即使在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_vstd::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的解决方案是一个很好的选择。

答案 4 :(得分:-1)

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

 #define is_type_signed(my_type) (((my_type)-1) < 0)