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

时间:2017-05-19 19:04:49

标签: c kernighan-and-ritchie

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

  

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

2 个答案:

答案 0 :(得分:1)

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

  

6.2.5类型

     

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

     

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

     CHAR_MIN中定义的

45) <limits.h>将具有值0SCHAR_MIN中的一个,这可以是   用来区分这两个选项。无论做出何种选择,char都是一个独立的类型   另外两个并且与两者都不兼容。

这定义了你对K&amp; R所说的引用。其他相关部分定义了基本执行字符集是什么。

  

5.2.1字符集

     

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

     

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

     

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

A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
     

拉丁字母的26个小写字母

a b c d e f g h i j k l m
n o p q r s t u v w x y z
     

10个十进制数字

0 1 2 3 4 5 6 7 8 9
     

以下29个图形字符

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

空格字符,控制字符表示水平制表符,垂直制表符和   形式饲料。源和执行的每个成员的表示基本   字符集应该适合一个字节。在源和执行基本字符集中,   上述小数位数列表中0之后的每个字符的值应大于1   以前的价值。在源文件中,应该有一些表示结束的方法   每行文字;本国际标准对待这样的终端指标就像它一样   是一个单行字符。在基本执行字符集中,应该有   控制表示警报,退格,回车和新行的字符。如果有的话   在源文件中遇到其他字符(标识符,字符除外)   常量,字符串文字,标题名称,注释或从不的预处理标记   转换为令牌),行为未定义。

     

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

     

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

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

答案 1 :(得分:0)

你需要先了解好几件事。

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

  2. 事实证明,负数在高位中始终为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标准不指定它是有符号还是无符号

    < / LI>

    总而言之,Kernighan和Ritchie所说的是当我们将char转换为16位或32位整数时,我们不太清楚如何应用第5步。如果我' m在类型char未签名的机器上,我取字符Ø并将其转换为int,我可能得到值216.但如果我在类型为{{1}的机器上}签名,我可能会得到数字-40。