有关char签名的问题

时间:2015-03-26 02:30:12

标签: c++ char language-lawyer signedness

根据标准,char是否已签名是实现定义的。这给我带来了一些麻烦。以下是一些例子:

1)测试最重要的位。如果char已签名,我只需将该值与0进行比较即可。如果未签名,我会将值与128进行比较。这两种简单方法都不是通用的,适用于这两种情况。为了编写可移植代码,似乎我必须直接操作这些位,这不是很好。

2)价值分配。有时,我需要将一个位模式写入char值。如果char是无符号的,则可以使用十六进制表示法轻松完成,例如char c = 0xff。但是,当char签名时,此方法不适用。以char c = 0xff为例。 0xff超出了签名char可以容纳的最大值。在这种情况下,标准表示c的结果值是实现定义的。

那么,有没有人对这两个问题有好的想法?关于第二个,我想知道char c = '\xff'对于签名和无签名char是否合适。

注意:有时需要将明确的位模式写入字符。请参阅http://en.cppreference.com/w/cpp/string/multibyte/mbsrtowcs中的示例。

5 个答案:

答案 0 :(得分:2)

1)测试MSB:(x | 0x7F) != 0x7F(或reinterpret_cast<unsigned char&>(x) & 0x80

2)reinterpret_cast<unsigned char&>(x) = 0xFF;

请注意,如果要将字符占用的内存视为位集合,则reinterpret_cast完全合适,绕过与char类型中任何给定值关联的特定位模式。

答案 1 :(得分:2)

如果您真的关心签名,只需根据需要将变量声明为signed charunsigned char。不需要与平台无关的比特伎俩。

答案 2 :(得分:0)

实际上,你可以做你想做的事而不用担心签名。

十六进制描述位模式而不是整数值。 (见免责声明)

所以对于2.你说你不能像这样分配位模式

  

char c = 0xff

但你真的可以这样做,签名与否。

对于1,您可能无法执行“与0比较”技巧,但您仍有几种方法可以检查最重要的位。一种方法是,向右移动7,在左边移动零,然后检查它是否等于1.独立于签名。

正如Tony D指出的那样,(x | 0x7F)!= 0x7F是一种更便携的方式,而不是移位,因为它可能不会以零移位。同样地,你可以做x&amp; 0x80 == 0x80。

当然你也可以做Brian建议的事情,只使用unsigned char。

免责声明:Tony指出0x实际上是一个int,并且当char不能保存值或者char是无符号时,转换为char是实现定义的。但是,没有任何实施会破坏这里的标准。 char c = 0xFF,天气或未签名或不签名,将填补这些位,相信我。找到一个不这样做的实现将非常困难。

答案 3 :(得分:0)

您可以分别使用两个0x7F0xFF对给定值进行OR和AND来检测并删除其signed_ness。

答案 4 :(得分:0)

测试MSB的最简单方法是使其成为LSB:char c = foo(); if ((c>>(CHAR_BIT-1)) & 1) ...

设置特定的位模式有点棘手。例如,全比特一可能不一定是0xff,但也可能是0x7ff,更实际的是0xffff。无论如何,~char(0)是全位 - 一位。有点不太明显,char(-1)也是如此。如果签署了char,那就很清楚;如果无符号,这仍然是正确的,因为无符号类型工作模2 ^ N.遵循该逻辑,char(-128)只设置8位,无论char中有多少位或是否已签名。