将字符转换为整数的微妙之处

有人可以清楚地解释K&R的这些线条实际意味着什么:

当char被转换为int时,它是否会产生负整数?答案因机器而异.C的定义保证了机器标准打印字符集中的任何字符都不会是负数 ,而是任意位模式存储在字符变量中的某些机器可能看起来是负面的,但对其他机器则是正面的“。

你需要先了解几件事。

  1. 如果我取一个8位值并将其扩展为16位值,通常你会想象只是在左边添加一堆0。 例如,如果我有8位值23,二进制为00010111,那么作为16位数字,它是0000000000010111,也是23。

  2. 事实certificate,负数在高位中始终为1。 (可能有奇怪的机器不适用于此,但对于您可能使用的任何机器都是如此。)例如,8位值-40以二进制表示为11011000。

  3. 因此,当您将带符号的8位值转换为16位值时,如果高位为1(即,如果该数字为负),则不会在左侧添加一堆0-s,你添加一堆1代替。 例如,回到-40,我们将11011000转换为1111111111011000,这是-40的16位表示。

  4. 还有无符号数字,永远不会消极。 例如,8位无符号数216表示为11011000.(您将注意到这是与带符号数-40相同的位模式。)当您将无符号8位数转换为16位时,添加无论如何,一堆0。 例如,您将11011000转换为0000000011011000,这是216位的16位表示。

  5. 所以,把这一切放在一起,如果你要将一个8位数转换成16位(或更多位),你必须看两件事。 首先,是签名还是未签名? 如果它是无符号的,只需在左边添加一堆0。 但是如果它已经签名,你必须查看8-0位数的高位。 如果它为0(如果数字为正),则在左侧添加一堆0。 但如果它是1(如果数字是负数),在右边添加一堆1。 (整个过程称为符号扩展 。)

  6. 普通的ASCII字符(如“A”,“1”和“$”)都具有小于128的值,这意味着它们的高位始终为0.但是“Latin-1”中的“特殊”字符或UTF-8字符集的值大于128.因此,它们有时也称为“高位”或“第八位”字符。 例如,Latin-1字符Ø(带有斜线的O)具有值216。

  7. 最后,尽管C中的char类型通常是8位类型, 但C标准不指定它是有符号还是无符号

综上所述,Kernighan和Ritchie所说的是当我们将char转换为16位或32位整数时,我们不太清楚如何应用第5步。如果我在一台类型为char的机器上是无符号的,我取字符Ø并将其转换为int,我可能会得到值216.但如果我在一个char类型的机器上,我可能会得到数字-40。

标准有两个或多或少的相关部分 – ISO / IEC 9899:2011。

6.2.5类型

¶3声明为char类型的对象足以存储基本执行字符集的任何成员。 如果基本执行字符集的成员存储在char对象中,则其值保证为非负值。 如果任何其他字符存储在char对象中,则结果值是实现定义的,但应在可以在该类型中表示的值的范围内。

¶15char, signed charunsigned char这三种类型统称为字符类型 。 实现应将char定义为具有与signed charunsigned char相同的范围,表示和行为。 45)

45)定义的CHAR_MIN将具有值0SCHAR_MIN ,这可用于区分这两个选项。 无论做出何种选择, char都是与其他两种类型不同的类型,并且与两者都不兼容。

这定义了您对K&R的报价。 其他相关部分定义了基本执行字符集的含义。

5.2.1字符集

¶1应定义两组字符及其关联的整理顺序:写入源文件的集合( 源字符集 ),以及在执行环境( 执行字符集 )中解释的集合 。 每个集合进一步划分为基本字符集 ,其内容由本子条款给出,以及一组零个或多个特定于语言环境的成员(不是基本字符集的成员),称为扩展字符 。 组合集也称为扩展字符集。 执行字符集的成员值是实现定义的。

¶2在字符常量或字符串文字中,执行字符集的成员应由源字符集的相应成员或由反斜杠\后跟一个或多个字符组成的转义序列表示。 所有位都设置为0的字节,称为空字符 ,应存在于基本执行字符集中; 它用于终止字符串。

¶3基本源和基本执行字符集应具有以下成员:拉丁字母表的26个大写字母

 ABCDEFGHIJKLM NOPQRSTUVWXYZ 

拉丁字母的26 个小写字母

 abcdefghijklm nopqrstuvwxyz 

10位十进制数字

 0 1 2 3 4 5 6 7 8 9 

以下29个图形字符

 ! " # % & ' ( ) * + , - . / : ; < = > ? [ \ ] ^ _ { | } ~ 

空格字符和控制字符表示水平制表符,垂直制表符和换页符。 源和执行基本字符集的每个成员的表示应该适合一个字节。 在源和执行基本字符集中,上述十进制数字列表中0之后的每个字符的值应比前一个值大1。 在源文件中,应该有一些方法来指示每行文本的结尾; 本国际标准将这样的行尾指标视为单个新行字符。 在基本执行字符集中,应有控制字符,表示警报,退格,回车和新行。 如果在源文件中遇到任何其他字符(标识符,字符常量,字符串文字,标题名称,注释或永远不会转换为标记的预处理标记除外),则行为未定义。

¶4 字母是上面定义的大写字母或小写字母; 在本国际标准中,该术语不包括其他字母表中的字母。

¶5通用字符名称构造提供了一种命名其他字符的方法。

这些规则的一个结果是,如果一台机器使用8位字符和EBCDIC编码,那么普通char必须是无符号类型,因为数字在EBCDIC中具有代码240..249。