简体   繁体   English

C ++中signed char的负值cout

[英]cout of negative value of signed char in C++

How C++ handles cout of negative value of signed char? C ++如何处理有问题的char的负值? Is the behavour defined in C++11 standard? 行为是用C ++ 11标准定义的吗? I am using MinGW C++ 11 compiler. 我正在使用MinGW C ++ 11编译器。 It looks the signed value is converted to unsigned type by adding 256 and then prints extended ASCII characters. 看起来有符号值通过添加256转换为无符号类型,然后打印扩展的ASCII字符。

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

According to this , the following overload is selected: 根据 ,下面的过载选自:

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

And since signed char is not char , a is first converted to a char using widen : 而且,由于signed char不是chara首先被转换为一个charwiden

char_type widen( char c ) const;

So your code is equivalent to: 所以你的代码相当于:

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

As you can see, widen takes a char , so you'll have a conversion from signed char to char prior to the actual "widening". 正如您所看到的, widen需要一个char ,因此在实际“扩展”之前,您将从signed char转换为char

Even if you are widening from a char to a char , the behavior is implementation-defined — The standard makes no guarantee regarding this. 即使您从char扩展到char ,行为也是实现定义的 - 标准不保证这一点。

Use type casting to int ... 使用类型转换来int ...

std::cout << (int)a;

...or, following better C++ programming style (as Christian Hackl suggested): ...或者,遵循更好的C ++编程风格(正如Christian Hackl建议的那样):

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

This actually does not answer your questions (already been answered by Holt), but shows a solution to the problem. 这实际上并没有回答你的问题(Holt已经回答了),但显示了问题的解决方案。

Most of this is required behavior (and most of what isn't still borders on being required). 其中大部分都是必需的行为(大部分内容仍然是必需的)。

To be specific, the C++ standard says that iostreams are associated with C-style input and output streams, so cout is associated with stdout (§[narrow.stream.objects]/3): 具体来说,C ++标准说iostream与C风格的输入和输出流相关联,因此coutstdout相关联(§[narrow.stream.objects] / 3):

The object cout controls output to a stream buffer associated with the object stdout , declared in <cstdio> . 对象cout控制输出到与<cstdio> stdout <cstdio>声明的对象stdout相关联的流缓冲区。

The C standard, in turn, defines narrow-character output as being as-if written via fputc (§7.19.3/12): 反过来,C标准将窄字符输出定义为如果通过fputc (第7.19.3 / 12节)写入:

The byte output functions write characters to the stream as if by successive calls to the fputc function. 字节输出函数将字符写入流,就好像通过连续调用fputc函数一样。

fputc requires (§7.19.7.3/2): fputc要求(§7.19.7.3/ 2):

The fputc function writes the character specified by c (converted to an unsigned char ) to the output stream pointed to by stream , [...] fputc函数将c指定的字符(转换为unsigned char )写入stream指向的输出stream ,[...]

So, yes, the conversion to unsigned char is exactly what the standards require. 所以,是的,转换为unsigned char正是标准所要求的。 The C standard requires that conversion from signed to unsigned (of any integer type, including char ) happen in the following fashion (§6.3.1.3/2): C标准要求从signed到unsigned(任何整数类型,包括char )的转换以下列方式发生(§6.3.1.3/ 2):

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type. 否则,如果新类型是无符号的,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内。

So yes, it is converted to unsigned by adding 256 (assuming unsigned char can represent values from 0 to 255, as is typical). 所以是的,通过添加256将其转换为无符号(假设unsigned char可以表示0到255之间的值,这是典型的)。

So that leaves us one part that the standard sort of attempts to require, without going quite all the way--the transformation that widen has to do (§[locale.ctype.virtuals]/10): 所以这给了我们标准的尝试要求的一部分,而不是完全一直 - widen的转变必须做(§[locale.ctype.virtuals] / 10):

Applies the simplest reasonable transformation from a char value or sequence of char values to the corresponding charT value or values. 将char值或char值序列中最简单的合理转换应用于相应的charT值。

Since it's a little difficult to decide exactly what's "reasonable", this could carry out some more or less arbitrary mapping on your character. 由于确定什么是“合理的”有点困难,这可能会对你的角色进行一些或多或少的任意映射。 In fact, it's apparently mapping input to output without modification (at least for the particular character you're writing), but it's true that other transformations could fall within "reasonable", and it would ultimately be difficult to draw a hard line saying that any particular transformation was not "reasonable". 实际上,它显然是在没有修改的情况下将输入映射到输出(至少对于你正在编写的特定字符),但是其他转换可能属于“合理”,并且最终难以画出强硬的说法任何特定的转变都不“合理”。

The other part that's not really required by the C++ (or any other) standard is how something else will interpret that output. C ++(或任何其他)标准并不真正需要的另一部分是其他东西将如何解释该输出。 All the language standards can mandate is what gets written to the stream. 所有语言标准都可以强制要求写入流。 The part with something else opening that stream and interpreting its content as "extended ASCII" (probably one of the ISO 8859 variants) is clearly outside the control of the language (or much of anything else in your program, of course). 打开该流并将其内容解释为“扩展ASCII”(可能是ISO 8859变体之一)的其他部分显然超出了语言的控制范围(当然,或者程序中的其他任何内容)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM