根据标准,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中的示例。
答案 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 char
或unsigned 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)
您可以分别使用两个0x7F
和0xFF
对给定值进行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中有多少位或是否已签名。