[英]What tools can diagnose C++ portability issues due to plain char signedness?
[英]Issues about the signedness of char
根据标准, char
是否签名是实现定义的。 这给我带来了一些麻烦。 以下是一些例子:
1)测试最重要的位。 如果char
已签名,我可以简单地将该值与0
进行比较。 如果未签名,我将该值与128
进行比较。 这两种简单方法都不是通用的,适用于这两种情况。 为了编写可移植代码,似乎我必须直接操作这些位,这不是很好。
2)价值分配。 有时,我需要为char
值写一个位模式。 如果char
是无符号的,则可以使用十六进制表示法轻松完成,例如, char c = 0xff
。 但是当char
签名时,此方法不适用。 以char c = 0xff
为例。 0xff
超出了signed char
可以容纳的最大值。 在这种情况下,标准说c
的结果值是实现定义的。
那么,有没有人对这两个问题有好的想法? 关于第二个,我想知道char c = '\\xff'
对于signed和unsigned char
是否正常。
注意:有时需要将明确的位模式写入字符。 请参阅http://en.cppreference.com/w/cpp/string/multibyte/mbsrtowcs中的示例。
1)测试MSB: (x | 0x7F) != 0x7F
(或reinterpret_cast<unsigned char&>(x) & 0x80
)
2) reinterpret_cast<unsigned char&>(x) = 0xFF;
请注意,如果要将字符占用的内存视为位集合,则绕过与char
类型中任何给定值关联的特定位模式, reinterpret_cast
是完全合适的。
如果您真的关心signed-ness,只需根据需要将变量声明为signed char
或unsigned char
。 不需要平台无关的比特伎俩。
实际上你可以做你想做的事而不用担心签名。
十六进制描述位模式而不是整数值。 (见免责声明)
所以对于2.你说你不能分配像这样的位模式
char c = 0xff
但你真的可以这样做,签名与否。
对于1,您可能无法执行“与0比较”技巧,但您仍有几种方法可以检查最重要的位。 一种方法是,向右移动7,在左边移动零,然后检查它是否等于1.独立于签名。
正如Tony D指出的那样,(x | 0x7F)!= 0x7F是一种更便携的方式,而不是移位,因为它可能不会以零移位。 类似地,你可以做x&0x80 == 0x80。
当然你也可以做Brian建议的,只使用unsigned char。
免责声明:Tony指出0x实际上是一个int,当char不能保存值或者char是无符号时,转换为char是实现定义的。 但是,没有任何实施会破坏这里的标准。 char c = 0xFF,天气或未签名或不签名,将填补这些位,相信我。 找到一个不这样做的实现将是非常困难的。
您可以分别使用两个0x7F
和0xFF
对给定值进行OR和AND来检测并删除其signed_ness。
测试MSB的最简单方法是使其成为LSB: char c = foo(); if ((c>>(CHAR_BIT-1)) & 1) ...
char c = foo(); if ((c>>(CHAR_BIT-1)) & 1) ...
设置特定的位模式有点棘手。 例如,全比特一可能不一定是0xff,但也可能是0x7ff,更实际的是0xffff。 无论如何, ~char(0)
是all-bits-one。 有点不太明显, char(-1)
也是如此。 如果签署了char,那就很清楚; 如果无符号,这仍然是正确的,因为无符号类型工作模2 ^ N. 遵循该逻辑, char(-128)
只设置8位,无论char中有多少位或是否有符号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.