C++中签名字符的负值

cout of negative value of signed char in C++

本文关键字:字符 C++      更新时间:2023-10-16

C++如何处理符号字符的负值?行为是否在 C++11 标准中定义?我正在使用 MinGW C++ 11 编译器。看起来有符号值通过添加 256 转换为无符号类型,然后打印扩展的 ASCII 字符。

signed char a=-35;
std::cout<<a;

据此,选择以下重载:

template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
signed char ch );

由于signed char不是chara首先使用widen转换为char

char_type widen( char c ) const;

所以你的代码等效于:

std::cout << std::cout.widen(c);
// or:
std::cout << std::use_facet< std::ctype<char> >(getloc()).widen(c)

如您所见,widen需要char,因此在实际"加宽"之前,您将从signed char转换为char

即使你从char扩展到char,行为也是实现定义的——标准对此不作任何保证。

使用类型转换来int...

std::cout << (int)a;

。或者,遵循更好的C++编程风格(如Christian Hackl所建议的那样):

std::cout << static_cast<int>(a);

这实际上并没有回答你的问题(霍尔特已经回答了),但显示了问题的解决方案。

其中大部分是必需的行为(大多数不是仍然

需要的行为)。具体来说,C++标准说iostreams与C风格的输入和输出流相关联,因此coutstdout相关联(§[narrow.stream.objects]/3):

对象cout控制输出到与对象stdout相关联的流缓冲区,在<cstdio>中声明。

反过来,C 标准将窄字符输出定义为通过fputc编写的 (§7.19.3/12):

字节输出函数将字符写入流,就像通过连续调用fputc函数一样。

fputc要求 (§7.19.7.3/2):

fputc函数将c指定的字符(转换为unsigned char)写入stream, [...]

所以,是的,转换为unsigned char正是标准所要求的。C 标准要求从有符号到无符号(任何整数类型,包括char)的转换按以下方式进行 (§6.3.1.3/2):

否则,如果新类型

是无符号的,则通过重复添加或减去比新类型中可以表示的最大值多一个来转换值,直到该值在新类型的范围内。

所以是的,它通过添加 256 转换为无符号(假设unsigned char可以表示从 0 到 255 的值,这是典型的)。

因此,这给我们留下了标准类型试图要求的一部分,而不是完全完成 -widen必须做的转换(§[locale.ctype.virtuals]/10):

将最简单的合理转换从 char 值或 char 值序列应用到相应的 charT 值。

由于要准确决定什么是"合理"有点困难,这可能会对你的角色进行一些或多或少的任意映射。事实上,它显然是在不加修改的情况下将输入映射到输出(至少对于您正在编写的特定字符),但确实其他转换可能属于"合理"的范围,并且最终很难划出一条强硬的界限说任何特定的转换都不是"合理的"。

C++(或任何其他)标准并不真正要求的另一部分是其他人将如何解释该输出。所有语言标准可以强制要求写入流的内容。打开该流并将其内容解释为"扩展 ASCII"(可能是 ISO 8859 变体之一)的部分显然超出了语言的控制范围(当然,或者程序中的许多其他内容)。