20135223何伟钦—信息安全系统设计基础第三周学习总结
信息的表示和处理
2.0三种数字表示
无符号:编码基于传统的二进制表示法,表示大于或者等于零的数字。
补码:编码是表示有符号整数的最常见的方式,有 符号整数就是可以为正或者为负的数字。
浮点数:编码是表示实数的科学记数法 的以二为基数的版本。
溢出(overflow)的例子:使用 32 位来表示数据类型int,计算表达式200*300*400*500会得出结果 -884 901 888。 这违背了整数运算的特性,计算一组正数的乘积不应产生一个为负的结果。
2.1信息存储
机器级程序将存储器视为一个非常大的字节数组,称为虚拟存储器。存储器的每个字节都由一个唯一的数字来标识,称为它的地址,所有可能地址的集合称为虚拟地址空间。
1.十六进制表示法
十六进制(简写为“hex”)
使用数字 ‘0’~‘9’,以及字符‘A’~‘F’来表示 16 个可能的值。(由于以前多次学习,已基本掌握)
2.字
每台计算机都有一个字长,指明整数和指针数据的标称大小。因为虚拟地址是以这样的一个字来编码的,所以字长决定的最重要的系统参数就是虚拟地址空间的最大大小。对于一个字长为w位的机器而言,虚拟地址的范围为0~2w-1,程序最多访问2w个字节,计算机多为32和64位。
3.数据大小
C声明 |
32位机器 |
64位机器 |
char |
1 |
1 |
Short int |
2 |
2 |
int |
4 |
4 |
Long int |
4 |
4 |
Char * |
4 |
8 |
float |
4 |
4 |
double |
8 |
8 |
l 声明指针(T *p;char *p)
4.寻址和字节顺序
小端法——在存储器中按照从最低有效字节到最高有效字节的顺序存储对象。
大端法——从最高有效字节到最低有效字节的顺序存储。
小端法:高对高,低对低。
大端法:高对低,低对高。
强制类型转换(cast):以一种数据类型引用一个对象,而这种数据类型与创建这个对象时定义的数据类型不同。
给C语言初学者:
①使用typedef命名数据类型:改善代码的可读性
②使用printf格式化输出:(同类fprintf和sprintf)打印信息
以'%'开始的字符序列都表示如何格式化下一个参数。
示例:'%d'是输出一个十进制整数,'%f'是输出一个浮点数,而'%c'是输出一个 字符,其编码由参数给出。
③指针和数组
用数组表示法来引用指针
用指针表示法来引用数组元素。
如:引用 start[i]表示我们想要读取以start指向的位置为起始的第i个位置处的字节。
④指针的创建和间接引用
取地址运算符&
&x创建了一个指向保存变量x的位置的指针
三个指针类型:int*、float*和void**。(数 据类型void*是一种特殊类型的指针,没有相关联的类型信息。)
强制类型转换运算符可以将一种数据类型转换为另一种。因此,强制类型转换(byte_ pointer)&x表明无论指针&x以前是什么类型,它现在就是一个指向数据类型为unsigned char的指针。这里给出的这些强制类型转换不会改变真实的指针,它们只是告诉编译器以新的 数据类型来看待被指向的数据。
5.表示字符串
C 语言中字符串被编码为一个以null字符结尾的字符数组
ASCLL编码:命令man ascii:得到ASCII字符码表
6.表示代码
二进制代码在不同的操作系统上有不同的编码规则。所以二进制代码是不兼容的
7.布尔代数
布尔代数运算(| 就是 OR(或),& 就是 AND(与),~ 就是 NOT(取反), ^ EXCLUSIVE-OR(异或))
① ~ 对应于逻辑运算 NOT:当 P 等于 0 时,~P 等于 1,反之亦 然。 ②& 对应于逻辑运算AND,只有当p =1且q =1时,p & q才等于1。
③|对应于逻辑运算OR,当p =1或者q =1时, p|q等于1
④^ 对应于逻辑运算异或,当p =1且q =0,或者p =0且q =1时,p^q等于1
8.C语言中的位级运算
位级运算:将十六进制的参数扩展成二进制表示并执行二进制运算,然后再转换回十六进制。
逻辑:逻辑运算符 “||、&&、!”分别对应于命题逻辑中的OR、AND、NOT运算。
移位:对于无符号数据,右移必须是逻辑的。而对于有符号数据,算术的或者逻辑的右移都可以。
运算:位向量按位进行逻辑运算,结果仍是位向量(区别于逻辑运算)
※常见用法:掩码——用来选择性的屏蔽信号
掩码是一个位模式,表示从一个字中选出的位的集合。
用位向量给集合编码,通过指定掩码来有选择的屏蔽或者不屏蔽一些信号
比如:某一位位置上为1时,表明信号i是有效的;0表示该信号被屏蔽。这个掩码就表示有效信号的集合。
例:0xFF,表示屏蔽除最低有效字节之外的所有字节。
所以任取一个数x=0x934ADFEC,x&0xFF=0x000000EC
~0:生成一个全1的掩码。
9.逻辑运算
逻辑运算符
与:&&
或:||
非:!
计算方法:所有非零参数都代表TRUE,0参数代表FALSE
逻辑运算的结果:1-代表TRUE;0-代表FALSE
逻辑运算和位运算的区别
l 只有当参数被限制为0或1时,逻辑运算才与按位运算有相同的行为。
l 如果对第一个参数求值就能确定表达式的结果,逻辑运算符就不会对后面的参数求值。
10.语言中的移位运算
1.左移<<
2.右移>>
逻辑右移:在左端补k个0,多用于无符号数移位运算
算术右移:在左端补k个最高有效位的值,多用于有符号数移位运算。
☆注意:Java中用>>表示算术右移,用>>>表示逻辑右移
移位运算优先级小于算术运算
2.2整数表示
1、整型数据类型
整型数据类型——表示有限范围的整数,每种类型都能用关键字来指定大小,还可以指定是非负数(unsigned)还是负数(默认)。这些不同大小的分配的字数会根据机器的字长和编译器有所不同。
要用ISO C99中的“long long”类型,编译时要用 gcc -std=c99
2、无符号数编码
无符号数的二进制表示的一个重要性质:0-(2^w)-1中的每一个整数和长度为w的位向量是一一对应的
3、补码编码
补码的范围:-2^(w-1)~2^(w-1)-1
在可表示的取值范围内的每个数字都有一个唯一的w位的补码编码
- 有符号数的其他表示方法:反码、原码
补码的利用寄存器的长度是固定的特性简化数学运算
4、有符号数和无符号数之间的转换
强制类型转换:结果保持位值不变,只是改变了解释这些位的方式
函数U2T:从无符号数到补码;T2U:从补码到无符号数
5.C语言中的有符号数和无符号数
无符号常量:后缀字符U或u
1.转换原则:底层的位保持不变
(1)有符号数→无符号数
非负数——保持不变
负数——转换成大正数
(2)无符号数→有符号数
以2^*(w-1)为界限:
小于它——保持不变
大于它——转换为负数值
[0,2^(w-1))范围内的数字,无符号和补码表示相同;范围之外的,需要加上或者减去2^w
2.运算时若同时存在有符号数和无符号数,会隐式的将有符号数强制类型转换为无符号数,并且假设这两个数都是非负的。
6、扩展一个数字的位表示
扩展:从一个较小的数据类型转换为较大的数据类型,同时保持数值不变。
1.零扩展:在开头加上0。多用于无符号数转换为一个更大的数据类型。
2.符号扩展:添加最高有效位的副本。多用于补码数字转换
7、截断数字
截断:减少表示一个数字的位数。而这么做可能会改变它的值,这也是溢出的一种形式。
将一个w位的数截断为k位数字时,就会丢弃高w-k位。
- 对于无符号数来说,就相当于 mod 2的k次幂
- 对于有符号数来说,先按照无符号数截断,然后再转化为有符号数
2.3 整数运算
1.无符号加法
等价于计算和mod2^w,直接丢弃x+y的w+1位表示的最高位
2.补码加法
本质:模掉w位的补码最高有效位的权重2的w次幂
结果:正溢出、正常、负溢出
- 两个数的w位补码之和与无符号之和有完全相同的位级表示
3.补码的非
x=-2^(w-1)时,为-2^(w-1)
x>-2^(w-1)时,为-x
- 补码的位级表示:
对每一位求补,再对结果+1
设k为最右面的1的位置,将k左边的所有位取反
4.无符号乘法
计算乘积模2
5.补码乘法
将2w位的乘积截断为w位。也就是说,需要mod 2的w次幂。
- 对于无符号和补码乘法来说,乘法运算的位级表示都是一样的
6.乘以常数
乘法指令很慢,而加法和移位相对较快。所以在编译器中,会使用移位和加法运算组合的方式来代替乘以常数因子
常数为2的k次幂的时候
直接左移k位即可。
常数不是2的整数次幂的时候
将常数C表示为2的几个整数次幂的和,结合移位运算和加法运算。
注意:溢出不影响结果
7.除以2的幂
机器运算中,除法比乘法更慢。当被除数为2的整数次幂时,通过右移来解决。右移时需要区分无符号数和补码。
- 注意:整数除法总是舍入到零
①无符号数——逻辑右移
无符号数除以2的k次幂,就等同于对其逻辑右移k位。
②补码——算术右移
补码进行算术左移时,需要考虑补码数的正负,因为整数除法总是舍入到零,无符号数中没有负数不必担心,但补码中有正有负,正数向下舍入到零,负数应该向上舍入到零。所以这里涉及到在移位前偏置。
也就是说:
- x≥0时,除以2的k次幂等价于将x算术右移k位
- x<0时,先将x加上(2^k)-1,再算术右移k位
4.浮点数
浮点表示对形如V=x X (2^y)的有理数进行编码,适用于非常大的数字、非常接近于0的数字或作为实数运算的近似值
不太关注精确;关注速度和简便性
1、二进制小数
将一个数表示为形如x/(2^k):将x的写成为二进制,并将二进制小数点插入从右边算起的第k个位置
2、IEEE浮点表示
1.IEEE浮点标准:
用V=(-1)^s*M*2^E来表示一个数:
符号:s决定这个数是正还是负。0的符号位特殊情况处理。
阶码:E对浮点数加权,权重是2的E次幂(可能为负数)
尾数:M是一个二进制小数,范围为1~2-ε或者0~1-ε(ε=1/2的n次幂
2. 编码规则:
单独符号位s编码符号s,占1位
k位的阶码字段exp编码阶码E
n位小数字段frac编码尾数M(同时需要依赖阶码字段的值是否为0)
3.两种精度
单精度(float),k=8位,n=23位,一共32位;
双精度(double),k=11位,n=52位,一共64位。
4.三种编码情况
- 规格化的值
即exp的位模式既不全0也不全1的时候,这是最一般最普遍的情况,因而是规格化的。
(1)阶码字段和阶码
这里是以偏置形式表示的有符号整数。
阶码E = e-Bias
Bias=[2^(k-1)-1]
(2)小数字段和尾数
二进制小数点在小数字段最高有效位的左边。
尾数M = 1+f(隐含的以1开头的表示)
- 非规格化的值
即阶码域全为0时的数。
(1)阶码
阶码E = 1-Bias
(2)尾数
尾数M = f(小数字段的值,不包含隐含的1)
(3)非规格化的功能:
a. 提供了一种表示数值0的方法。
b. 表示那些非常接近零的数。逐渐溢出
- s 特殊值
特殊值是在阶码位全为1的时候出现的。分为两种情况:
(1)无穷:小数字段全为0
(2)NaN不是一个数
小数字段非0
一些运算的结果不能是实数或无穷的时候会返回这样的值。或者表示未初始化的数据。
3.数字示例
看书理解,这里不做详细说明
4.舍入
舍入:找到和数值x最接近的匹配值x',可以用期望的浮点形式表示出来。
①向偶舍入
即:将数字向上或向下舍入,是的结果的最低有效数字为偶数。(四舍六入,五求偶)
能用于二进制小数。
②向零舍入
即:把整数向下舍入,负数向上舍入。
③向下舍入
正数和负数都向下舍入。
④向上舍入
正数和负数都向上舍入。
5.浮点运算
①浮点加法
浮点加法是可交换的
浮点加法不具结合性
大多数值的浮点加法都有逆元,除了无穷和NaN。
浮点加法满足单调性
②浮点乘法
浮点乘法是可交换的
浮点乘法不具有结核性
浮点乘法的单位元为1.0
浮点乘法在加法上不具备分配性
在一定条件下满足单调性
6.C语言中的浮点数
两种浮点数类型:float和double
int、float、double的相互强制类型转换(int是32位的)
int → float 不会溢出但有可能舍入
int/float → double 结果保留精确数值
double → float 可能溢出为±∞,由于精确度较小也有可能被舍入
float/double → int 向零舍入,可能溢出。
学习体会
在这周的学习中,我学习了用各类方法来表示基本的数据类型,再操作这些数据。在核心部分,我们需要方法来表示基本数据类型,然后考虑到编译器如何将C程序翻译成这样的指令。在接下来学习的几种实现处理的方法,帮助我们更好的了解硬件资源是如何被用来执行的,从而分析最大程序化的性能。
在了解了这些编译器和机器级代码,在今后的C程序编写时就可以获得最高性能。在掌握了这些技术后我们将会写出安全、可靠的充分利用计算机资源的程序。