关于char的签名性的问题

Issues about the signedness of char

本文关键字:问题 char 关于      更新时间:2023-10-16

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

1) 测试最高有效位。如果char是有符号的,我可以简单地将该值与0进行比较。如果无符号,我会将该值与128进行比较。这两种简单的方法都不是通用的,适用于这两种情况。为了编写可移植代码,我似乎必须直接操作这些位,这并不整洁。

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

所以,有人对这两个问题有好的想法吗?关于第二个,我想知道char c = 'xff'对于有符号和无符号的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是完全合适的。

如果您真的关心有符号的ness,只需根据需要将变量声明为signed charunsigned char。不需要独立于平台的比特处理技巧。

您可以将给定值分别与两个0x7F0xFF进行OR和and运算,以检测和删除其signed_ness。

实际上,您可以随心所欲,而不用担心签名性。

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

2也是如此。你说你不能像这个那样分配比特模式

char c=0xff

但不管签不签,你都可以做到。

对于1,您可能无法执行"与0进行比较"的技巧,但您仍然有几种方法来检查最高有效位。一种方法是,向右移动7,向左移动0,然后检查它是否等于1。与签名无关。

正如Tony D所指出的,(x|0x7F)!=0x7F是一种更便携的方法,而不是移位,因为它可能不会移位到零。类似地,你可以做x&0x80==0x80。

当然,您也可以按照Brian的建议,只需使用一个无符号字符。

免责声明:Tony指出,0x实际上是一个int,当char不能容纳值或char是无符号的时,转换为char是实现定义的。然而,没有任何实现会打破这里的标准。charc=0xFF,不管是weather还是unsigned,都会填充这些位,相信我。要找到一个不这样做的实现将非常困难。

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

设置一个特定的位模式有点棘手。例如,所有比特1可能不一定是0xff,但也可以是0x7ff,或者更实际地是0xffff。无论如何,~char(0)都是位1。char(-1)也不那么明显。如果char是签名的,那就很清楚了;如果无符号,这仍然是正确的,因为无符号类型工作模2^N。根据该逻辑,char(-128)只设置8位,而不管字符中有多少位或是否有符号。