如何检查纯字符是有符号的还是无符号的
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
。)
但正如本杰明·林德利的回答所暗示的那样,std::numeric_limits<char>::is_signed
可能更清楚地表达了意图。
(另一方面,我建议的方法也可以应用于C.)
使用unsigned char
"始终"可能会给您带来一些有趣的惊喜,因为大多数C风格函数(如printf
、fopen
)将使用char
,而不是unsigned char
。
edit: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)
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 将无符号char*转换为std::istream*C++
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- C++中无符号字符溢出
- 使用无符号字符数组有效存储内存
- 如何打印boost多精度128位无符号整数
- C++模板函数,用于比较任何无符号整数和有符号整数
- 在 std::无符号字符的向量处存储 int 的十六进制表示形式
- 获取隐式转换溢出从无符号到已签名的警告
- 如何在保持其值的同时将 c++ 无符号字符变量转换为 char 变量
- 从 std::vector<无符号字符>切片中提取 int?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 无法在 Arduino 中uint8_t数组转换为无符号长整型数组
- 将无符号字符的向量存储在数组中会给我 std::bad_alloc
- 使用 fopen 打开 .pak 文件并使该文件应用于 const 无符号字符* (C++)
- 未定义的符号:符号引用错误.没有输出写入主
- 符号"符号"的偏移不一致
- 未定义的符号 - 符号查找错误