第二章 信息的表示和处理 第一节 信息存储

本文介绍了计算机内存管理的基础知识,包括虚拟内存、地址空间、数据的十六进制表示法、字数据大小及其与指针的关系。讨论了字节顺序在多字节对象存储中的作用,以及C语言中的字符串和移位运算。强调了不同平台间的兼容性和程序的可移植性问题。
摘要由CSDN通过智能技术生成

2.1 信息存储

1、概述

1. 几个基本概念

  • 最小的可寻址的内存单位为一个8位的块,也就是一个字节。

  • 机器级程序将内存视为一个非常大的字节数组, 称为虚拟内存 (virtual memory)

  • 内存的每个字节 都由一个唯一的数字来标识, 称为它的地址( ad­dress),

  • 所有可能地址的集合就称为虚拟地址空间(virtual address space)

    顾名思义, 这 个虚拟地址空间只是一个展现给机器级程序的概念性映像。 实际的实现(见第9章)是将动态随机访问存储器(DRAM)、闪存、 磁盘存储器、 特殊硬件和操作系统软件结合起来, 为 程序提供一个看上去统一的字节数组。

2、十六进制表示法

1. 基本概念

十六进制(简写为 “hex")使用数字 ‘0’~'9’以及字符 ‘A’~ 'F’来表示16个可能的值。用十六进制书写,一个字节的值域为 0 0 16 00_{16} 0016 ~ F F 16 FF_{16} FF16​​。也就是一个字节可以由两位16进制数字表示。
在这里插入图片描述

2.进制转换

根据定义即可完成转换

  1. 十六进制转换成二进制

    可以通过展开每个十六进制数字,将它转换为二进制格式,例如0x173A4C
    在这里插入图片描述
    就可以得到结果

  2. 二进制转十六进制

    可以通过首先把它分为每4位一组来转换为十六进制。不过要注意,如果位总数不是4的倍数,最左边的一组可以少于4位,前面用0补足。然后将每个4位组转换为相应的十六进制数字。
    在这里插入图片描述

  3. 十进制转换成十六进制

    将一个十进制数字 x 转换为十六进制 ,可以反复地用16除x, 得到一个商q和一个余数r, 也就是 x=q • 16+r。 然后, 我们用十六进制数字表示的r作为最低位数字, 并且通过对q反复进行这个过程得到剩下的数字。 例如, 考虑十进制 314156的转换:
    在这里插入图片描述
    我们能读出十六进制表示为0x4CB2C

  4. 十六进制转换为十进制
    我们可以用相应的16的幕乘以每
    个十六进制数字。比如, 给定数字Ox7AF, 我们计算它对应的十进制值为7•162 +10-
    16+15 = 7 • 256+10 • 16+15 = 1792+160+15 = 1967。

3、字数据大小

1.字长字节数

用来指明指针数据的标称大小,也就是一个指针占用的字节数。因为 虚拟地址是以这样的一个字来编码的, 所以字长决定的最重要的系统参数就是虚拟地址空间的最大大小。也就是说,对于一个字长为w位的机器而言,其虚拟地址的范围为 0   2 w − 1 0~2^w - 1 0 2w1,程序最多访问 2 w 2^w 2w个字节。
我们常说的32位机器和64位机器指的就是字长。

我们将程序称为“ 32位程序 ” 或 “64位程序”时, 区别在于该程序是如何编译的,而不是其运行的机器类型。64位的机器也可以运行为32位机器编译的程序 。但是后者不能运行为前者编译的程序。

2.各种数据类型的字节数


上图是基本C数据类型的典型大小。分配的字节数受程序是如何编译的影响而变化。
本图给出的是32位和64位程序的典型值。
ISO C99 引入了 一类数据类型, 其数据大小是固定的, 不随编译器和机器设置而变化。 其中就有数据类型 int32_t 和 int64_t, 它们分别为 4 个字节和 8 个字节。
图中可以看到char*代表的指针使用的是程序的全字长,long在不同位的机器上所占的字长也不一样。

程序员应该切实的提高程序对于不同机器和编译器的可移植性。其一方面就是让程序对于不同数据类型的确切大小不敏感。比如, 假设一个声明为 int类型的程序对象能被用来存储一个指针。 这在大多数 32 位的机器上能正常工作, 但是在一台 64 位的机器上却会导致问题。

4、寻址和字节顺序

对于跨越多个字节的程序对象来说,必须明确两个问题

  • 用哪个字节的地址来表示整个对象的地址
  • 内存中如何排列这些字节

1.对象的地址

在几乎所有的机器上, 多字节对象都被存储为连续的字节序列, 对象的地址为所使用字节中最小的地址。
例如 一个int型变量,他的地址是0x100,他的四个字节依次被存储在0x100、0x101、0x102、0x103这几个位置。

2.排列顺序

对于一个数字x,假设其位表示为 [ x w − 1 , x w − 2 , . . . , x 1 , x 0 ] [x_{w-1},x_{w-2},...,x_1,x_0] [xw1,xw2,...,x1,x0],其中 x w − 1 x_{w-1} xw1是最高有效位, x 0 x_0 x0为最低有效位。如果w是八的倍数,那么就可以被分成若干个字节,这些字节的排序有两种情况

  1. 小端法
    就是最低有效字节在最前面

  2. 大端法
    就是最低有效字节在最后面

例如假设变量x 的类型为int, 位于地址0x100处, 它的十六进制值为0x01234567。地
址范围0x100~ 0x103 的字节顺序依赖于机器的类型:
在这里插入图片描述
选择好确定的操作系统之后,字节顺序就固定下来了。

在C 语言中,我们能够用数组表示法来引用指针,同时我们也能用指针表示法 来引用数组元素。在这个例子 中·,引用start[i]表示我们想要读取以start 指向的位置为起始的第i个位置处的字节。

5、表示字符串

c语言中,字符串被编码为一个以null结尾的字符数组。每个字符都由某个标准编码来表示, 最常见的是ASCII 字符码。 在使用 ASCII 码作为字符码的任何系统上都将得到相同的结果, 与字节顺序和字大小规则无关。 因而, 文本数据比二进制数据具有更强的平台独立性。

UTF-8
UTF-8编码,是变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1识别。这样对以7位ASCII字符为主的西文文档就大幅节省了编码长度
Java编程语言使用Unicode来表示字符串。 对于C语言也有支持Unicode的程序库。

6、表示代码

不同的机器类型使用不同的且不兼容的指令和编码方式。 即使是完全一样的进程, 运行在不同的操作系统上也会有不同的编码规则, 因此二进制代码是不兼容的。 二进制代码很少能在不同机器和操作系统组合之间移植。

7、布尔代数简介

最简单的布尔代数是在二元集合{0,1}的基础上结合几种运算符号定义的。
在这里插入图片描述
可以将上面四个布尔运算扩展到向量中去。位向量是一种固定长度w,由0和1组成的向量。
位向量一个很有用的应用就是表示有限集合。
位向量a = [01101001]表示集合A={0, 3, 5, 6},而b=[01010101]表示集合B ={0, 2, 4, 6}。使用这种编码集合的方法,布尔运算I和&分别对应于集合的并和交,而~对应于于集合的补。还是用前面那个例子,运算a&b得到位向量[01000001],而A交B = {0, 6}。

8、c语言中的移位运算

1.左移

<< 运算符将会将x向左边移动k位,丢弃最高的k位,并在最右边补齐k个0

2.右移

>> 运算符将会将x向右边移动k位,丢弃最低的k位,但是补齐有两种方式

  • 逻辑右移
    在左端补k个0
  • 算数右移
    在左端补k个最高有效位的值
    我们看下面的例子
    在这里插入图片描述
    实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移。

C语言标准
没有明确定义对于有符号数应该使用哪种类型的右移
对于一个w位的数据,移动k>=w位的时候,没有定义应该如何计算。
实际上许多机器上 位移量就是通过计算k mod w得到的

Java对于如何进行右移有明确的定义。表达是x>>k会将x算术右移k个位置,而x>>>k会对x做逻辑右移。
Java特别要求位移数量应该按照我们前面所讲的求模的方法来计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值