信息表示和处理

本文深入探讨信息在计算机中的表示,从十六进制、字数据大小、寻址和字节顺序到字符串的ASCII码表示。接着详细介绍了整数的无符号编码和补码编码,以及整数运算中的加法、乘法和移位。最后,文章讲解了浮点数的二进制小数表示和IEEE754浮点标准,包括浮点数的舍入规则和转换原则。
摘要由CSDN通过智能技术生成

信息表示和处理

  1. 现代计算机存储和处理信息以二进制表示。

  2. 三种重要的数字表示:

    1. 无符号编码:基于传统的二进制表示法,表示>=0的数字
    2. 补码编码: 表示有符号整数的最常见的方式
    3. 浮点数编码: 是表示实数的科学计数法的以2位基数的版本
  3. 计算机的表示法是用有限数量的位来对一个数字编码,因此结果溢出表示范围时,会出现异常的结果。

  4. 整数和浮点数的表示区别

    1. 整数只能编码一个相对较小的数值范围,但是这种表示是精确的。
    2. 浮点数虽然可以表示一个较大的数值范围,但是这种表示是近似的

2.1 信息存储

  1. 大多数计算机使用字节(byte),作为最小的可寻址的内存单位,而不是访问单独的位(bit)
  2. 机器级程序将内存视为一个非常大的字节数组,称为虚拟内存 (virtual memory)
  3. 内存中的每个字节都由一个数字进行标识,即为它的地址(address)
  4. 所有可能的地址集合,称为虚拟地址空间(virtual address space)
  5. 每个程序对象都可以视为一个字节块,程序本身就是一个字节序列
  6. C语言中一个指针(无论它指向一个整数或是一个结构,或是一个对象等等)的值就是某个存储块的第一个字节的虚拟地址。
2.1.1 十六进制表示法
  1. 一个字节由8位组成,值的范围用二进制表示 00000000 ~ 11111111,用十进制表示位0~255。使用过程中,如果用二进制表示太冗长,如果用十进制表示则与二进制转换太麻烦。所以引入了16进制。
  2. 十六进制:使用数字’0’ ~'9’以及字符 ‘A’ ~ ‘F’(大小写都可)表示16个可能的值。
  3. c语言中以0x或0X开头来标识十六进制,所以一个字节的值范围即为 0x00-0xFF。一个十六进制位由4个二进制位表示
2.1.2 字数据大小
  1. 字长(word size)指明指针数据的标称(nominal size)大小。

  2. 字长决定的最重要的系统参数就是虚拟地址空间的最大大小

    对于一个字长为w位的机器而言,虚拟地址的范围为0~(2的w次方-1)。即程序最多访问(2的w次方)个字节
    
  3. 32位字长的机器限制的虚拟地址空间为4GB(2的32次方个byte),64位的字长的机器限制的虚拟地址空间为16EB(1.84 * 10的19次方个字节 )

  4. 32位程序和64位程序的区别

    1 区别在于该程序是如何编译的,而不是其运行的机器类型
     prog.c使用下列伪指令编译
     linux>gcc -m32 prog.c 32位程序
     linux>gcc -m64 prog.c 64位程序
    2 程序是向后兼容的,所以32位的程序可以运行到64位的机器上。但是64位的程序不能运行在32位的机器上。
     
    
  5. c语言对各种不同数据类型,在32位和64机器上分配的字节数

    有符号 无符号 32位 64位
    [signed] char unsigned char 1 1
    short unsigned short 2 2
    int unsigned 4 4
    long unsigned long 4 8
    int32_t uint32_t 4 4
    int64_t uinit64_t 8 8
    char * 4 8
    float 4 4
    double 8 8
    我们可以看到有些数据类型的确切字节数依赖于程序是如何被编译的,数据类型long在32位程序中为4字节,在64位程序中为8字节。为了避免依赖"典型"大小和不同编译器设置带来的奇怪行为。在ISO C99引入了一类数据类型,其数据大小是固定的,不随编译器和机器设置而改变。其中就有int32_t,int64_t。
    
2.1.3 寻址和字节顺序
  1. 对于跨越多字节的程序对象,我们必须建立两个规则:

    • 这个对象的地址是什么
    • 在内存如何排列这些字节
  2. 多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址。

    例如: int类型的变量x的地址为0x100,即为地址表达式&x的值为0x100。
    那么变量x的4个字节将被存储在0x100, 0x101, 0x102, 0x103位置
    
  3. 排列换一个对象的字节有两个通用的规则

    1. 小端法(little endian): 最低有效字节在最前面
    2. 大端法(big endian):最高有效字节在最前面
    假设变量x的类型为int, 位于地址0x100处,它的十六进制值为0x01234567, 其最高字节为0x01,最低字节为0x67,其地址范围为0x100-0x103。
    
    大端法
    ...   0x100     0x101     0x102  0x103
    ...    01        23        45     67  
    
    小端法
    ...   0x100     0x101     0x102  0x103
    ...    67        45        32     01  
    
    1 大端法和小端法没有优劣之分。一个系统采用的是大端还是小端,要看厂商。一旦选择了操作系统,那么字节顺序也就固定下来了。
    2 现代有些新的微处理器是双端法,也就是可以配置作为大端或小端的机器运行
    3 Android和iOS采用的是小端法。
    
2.1.4 表示字符串
2.1.4.1 ASCII码表
  • 终端执行$ man ascii
八进制表示
     000 nul  001 soh  002 stx  003 etx  004 eot  005 enq  006 ack  007 bel
     010 bs   011 ht   012 nl   013 vt   014 np   015 cr   016 so   017 si
     020 dle  021 dc1  022 dc2  023 dc3  024 dc4  025 nak  026 syn  027 etb
     030 can  031 em   032 sub  033 esc  034 fs   035 gs   036 rs   037 us
     040 sp   041  !   042  "   043  #   044  $   045  %   046  &   047  '
     050  (   051  )   052  *   053  +   054  ,   055  -   056  .   057  /
     060  0   061  1   062  2   063  3   064  4   065  5   066  6   067  7
     070  8   071  9   072  :   073  ;   074  <   075  =   076  >   077  ?
     100  @   101  A   102  B   103  C   104  D   105  E   106  F   107  G
     110  H   111  I   112  J   113  K   114  L   115  M   116  N   117  O
     120  P   121  Q   122  R   123  S   124  T   125  U   126  V   127  W
     130  X   131  Y   132  Z   133  [   134  \   135  ]   136  ^   137  _
     140  `   141  a   142  b   143  c   144  d   145  e   146  f   147  g
     150  h   151  i   152  j   153  k   154  l   155  m   156  n   157  o
     160  p   161  q   162  r   163  s   164  t   165  u   166  v   167  w
     170  x   171  y   172  z   173  {   174  |   175  }   176  ~   177 del
     
十六进制表示

     00 nul   01 soh   02 stx   03 etx   04 eot   05 enq   06 ack   07 bel
     08 bs    09 ht    0a nl    0b vt    0c np    0d cr    0e so    0f si
     10 dle   11 dc1   12 dc2   13 dc3   14 dc4   15 nak   16 syn   17 etb
     18 can   19 em    1a sub   1b esc   1c fs    1d gs    1e rs    1f us
     20 sp    21  !    22  "    23  #    24  $    25  %    26  &    27  '
     28  (    29  )    2a  *    2b  +    2c  ,    2d  -    2e  .    2f  /
     30  0    31  1    32  2    33  3    34  4    35  5    36  6    37  7
     38  8    39  9    3a  :    3b  ;    3c  <    3d  =    3e  >    3f  ?
     40  @    41  A    42  B    43  C    44  D    45  E    46  F    47  G
     48  H    49  I    4a  J    4b  K    4c  L    4d  M    4e  N    4f  O
     50  P    51  Q    52  R    53  S    54  T    55  U    56  V    57  W
     58  X    59  Y    5a  Z    5b  [    5c  \    5d  ]    5e  ^    5f  _
     60  `    61  a    62  b    63  c    64  d    65  e    66  f    67  g
     68  h    69  i    6a  j    6b  k    6c  l    6d  m    6e  n    6f  o
     70  p    71  q    72  r    73  s    74  t    75  u    76  v    77  w
     78  x    79  y    7a  z    7b  {    7c  |    7d  }    7e  ~    7f del
     
     
十进制表示
      0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel
       8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si
      16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb
      24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us
      32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '
      40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /
      48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7
      56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?
      64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G
      72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O
      80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W
      88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _
      96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g
     104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o
     112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w
     120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del
2.1.4.2 字符串
  1. c语言中字符串被编码为一个以null(其值为0)字符结尾的字符数组。每个字符都以某个标准编码来表示。最常见的就是ASCII字符码。

    对字符串 "12345", 参照ASCII码表,其十六进制字节码为  31 32 33 34 35 00。
    
  2. 在使用ASCII字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因此,文本数据比二进制数据具有更强的平台独立性。

    文字编码的Unicode标准

    1 ASCII字符集适合编码英语文档,无法表示特殊字符,如中文,俄文等语言。

    2 Unicode统一字符集,使用32位来表示字符。这好像是要求每个字符要占用4个字节。

    3 不过,常见的字符只需要1个或2个字节,而不太常用的字符需要多一些字节数。

    4 UTF-8将每个字符编码为一个字符序列,其包含ASCII编码。

    5 Java使用Unicode来表示字符串。对于C语言也有支持Unicode的程序库。

2.1.5 表示代码

下面的c函数

int sum(int x, int y) {
    return x + y;
}

当在不同机器上编译时,生成如下字节表示的机器代码;

Linux32 55 89 e5 8b 45 0c 03 45 08 c9 c3 
Windows 55 89 e5 8b 45 0c 03 45 08 5d c3 
Sun     81 c3 e0 08 90 02 00 09
Linux64 55 48 89 e5 89 7d fc 89 75 f8 03 45 fc c9 c3 
  1. 我们发现指令编码是不同的,不同机器类型使用不同的且不兼容的指令和编码方式。

  2. 即使完全一样的进程,运行在不同的操作系统上也会有不同的编码规则,因此二进制代码是不兼容的。

  3. 二进制代码很少能够在不同机器和操作系统组合之间进行移植。

2.1.6 布尔代数简介

简而言之,就是使用 &(与),|(或),~(非),^(异或)进行位运算

位向量 [0110] 和 [1100]进行位运算
  
  0110    0110   0110    
& 1100  | 1100 ^ 1100  ~ 1100
  ----    ----   ----    ----
  0100    1110   1010    0011
  
1 运算规则
 & 同真为真
 | 一真为真
 & 不同为真
 ~ 按位取反
2 对于任何值与自己本身异或,值为0
  x ^ x = 0
3 利用^来交换x和y的值   
   x = x ^ y  
   y = x ^ y   ===> (y = x ^ y ^ y) ====> (y = x )
   x = x ^ y   ===> (x = x ^ y ^ x) ====> (x = y )
2.1.7 C语言中的位级运算
C的表达式 二进制表达式 二进制结果 十六进制表达式
~0x41 ~[0100 0001] [1011 1110] 0xBE
~0x00 ~[0000 0000] [1111 1111] 0xFF
0x69&0x55 [0110 1001]&[0101 0101] [0100 0001] 0x41
0x69|0x55 [0110 1001]|[0101 0101] [0111 1101] 0x7D
  1. 正如上表所示,进行位运算时,将其他进制转换成二进制,然后进行位运算后,再转回所需的进制。

  2. 位级运算的一个常见用法是实现掩码运算。这里的掩码是一个位模式,表示从一个字中选出的位的集合。

    1. 对于一个字长为32位的机器,掩码0xFF表示一个字的最低字节。
    2. 对于x = 0x89ABCDEF, x&0xFF = 0x000000EF, 只会保留x的最低字节,其他字节均为0。
    3. ~0将会生成一个全为1的掩码,不管机器的字大小是多少。
    4. 尽管对于32位的机器来说,掩码可以写为0xFFFFFFFF,但是这样的代码不是可移植的。
    
    
2.1.8 C语言中的逻辑运算
  1. 逻辑运算符: ||, &&,!

  2. 逻辑运算中认为所有非0的参数都表示true,参数0表示false。

    表达式 结果
    !0x41 0x00
    !0x00 0x01
    !!0x41 0x01
    0x69&&0x55 0x01
    0x69||0x55 0x01
  3. 具有短路机制,如果第一个表达式的结果已经能够确认整个表达式的值,那么第二个表达式就不会进行运算。

2.1.9 C语言中的移位运算
  1. 左移:对于操作数x, 向左移动k位,将丢弃最高的k位,并在右端补k个0

    操作数x: 0101 1001    
        (01)0110 0100  向左移动2位,最高的2位被丢弃,右端补2个0
        
    //无符号数和有符号数都用左移
    
  2. 右移: 逻辑右移和算术右移

    逻辑右移:向右移动k位,低位丢弃,高位补0
    算术右移:向右移动k位,低位丢弃,高位补最高有效位的值
    
    算术右移:用于操作有符号数
    逻辑右移:用于操作无符号数
    
  3. 移位示例

    操作
    参数x (0110 0011) (1001 0101)
    x << 4 (0011 0000) (0101 0000)
    x >> 4 逻辑右移 (0000 0110) (0000 1001)
    x >> 4 算术右移 (0000 0110) (1111 1001)
  4. C语言虽然没有规定对于有符号数应该运用哪种形式的右移。但是,实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移,且程序员也是假设机器对有符号数使用算术右移。

  5. 对于无符号数,右移必须是逻辑的。

  6. Java对右移有明确的定义。

    • x >> k , 会将x做算术右移
    • x>>>k,会对x做逻辑右移
  7. 一个数w位,当移动的位数k大于等于w时,该如何处理?

    实际移动的位数是 =  k % w;
    
    int lval = 0xFEDCBA98   << 32   w=32 k = 32  向左位移0位 =====》0xFEDCBA98
    int aval = 0xFEDCBA98   >> 36   w=32 k = 36  向右位移4位 =====》0xFFEDCBA9
    int uval = 0xFEDCBA98u  >> 40   w=32 k = 40  向右位移8位 =====》0xFFFEDCBAu
    

2.2 整数表示

  1. 用位来编码整数的两种不同的方式: 一种只能表示非负数。另一种能够表示正数,零,负数。
2.2.1 整型数据类型
  1. 32位程序上, C语言整型数据类型的典型取值范围

    [外链图片转存失败(img-lLTpf5gz-1564652354825)(./image/2-32位范围.png)]

  2. 64位程序上, C语言整型数据类型的典型取值范围

    [外链图片转存失败(img-fpZCJMLd-1564652354828)(./image/2-64位范围.png)]

  3. C语言标准定义了美中数据类型必须能够表示的最小的取值范围

    [外链图片转存失败(img-pBtWYbE3-1564652354828)(./image/2-最低范围.png)]

2.2.2 无符号的编码

对于一个w位的无符号编码,其值的范围为0 ~ (2的w次方 - 1)

2.2.3 补码编码
  1. 补码是最常见的表示有符号数的形式。其最高位为符号位。它的权重为-2[w-1](即为-2的w-1次方)

    由下列补码求其值
    0001 = - 0 * 2[3] + 0 * 2[2] + 0 * 2[1] + 1 * 2[0] =  0 + 0 + 0 + 1 =  1
    0101 = - 0 * 2[3] + 1 * 2[2] + 0 * 2[1] + 1 * 2[0] =  0 + 4 + 0 + 1 =  5
    1011 = - 1 * 2[3] + 0 * 2[2] + 1 * 2[1] + 1 * 2[0] = -8 + 0 + 2 + 1 = -5
    1111 = - 1 * 2[3] + 1 * 2[2] + 1 * 2[1] + 1 * 2[0] = -8 + 4 + 2 + 1 = -1
    
  2. 从上面的计算中可以得到w位的补码所能表示的值的范围

    其最小值为 [10....0](w) = -2[w-1]
    其最大值为 [01....1](w) = 2[w-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值