20155208《信息安全系统设计基础》第十三周学习总结
学习任务
- 找出全书你认为最重要的一章,深入重新学习一下,要求
- 完成这一章所有习题
- 详细总结本章要点
- 给你的结对学习搭档讲解你的总结并获取反馈
重新学习第二章内容
我认为无论是什么学科,只有打好基础,才能进行更深一步的学习与理解,所以我决定重新着重学习第二章的内容:信息的表示与处理。
第二章教材内容学习总结
- 一个字节由8位组成
- 在C语言中,以Ox和OX开头的数字常量被认为是十六进制的值。
- 其他进制表示法:二进制(B),十进制(D),八进制(O或者Q),十六进制(H)
- 三中重要的数字表示
无符号[表示大于或等于零的数字]
补码[二进制补码][表示有符号整数]
浮点数[表示实数的科学计数法的以二为基数的版本]
- 进制转换
进制转换,注意拿二进制作中间结果就好转了 数据大小
gcc -m32
可以在64位机上(比如实验楼的环境)生成32位的代码
- 寻址和字节顺序
最低有效字节在最前面的方式,小端法
最高有效字节在最前面的方式,大端法
进行书上练习2.4
习题总结: 注意进行十六进制加减法时的进位和退位时每个单位是以16的n次幂为基础进行的。
- 理论来说,对于一个字长为w位的机器来说,虚拟地址的范围是0~2w-1。程序最多访问2w个字节。
- C语言支持整数和浮点数的多种数据格式。
- 在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为使用地址中最小的地址。
- C语言中的typedef声明提供了一种给数据类型命名的方式。这能极大地改善代码的可读性,因为深度嵌套的类型声明很难读懂。它使用的是类型名而不是变量名,eg:
typedef int *int_pointer;
int_pointer ip;
- Linux 32、Windows和Sun的机器使用的是4字节地址,而Linux 64使用的是8字节地址。
- 运行书上代码 实现交换功能
#include<stdio.h>
#define Max 10
void inplace_swap(int *x,int *y)
{
*y = *x^*y;
*x = *x^*y;
*y = *x^*y;
}
void reverse_array(int a[],int cnt)
{
int first,last;
for(first = 0,last =cnt-1;
first<=last;
first++,last--)
inplace_swap(&a[first],&a[last]);
}
void main()
{
int MAX;
int a[MAX];
int count,i;
printf("please enter the amount of numbers(no more %d):\n",MAX);
scanf("%d",&count);
printf("please enter any numbers as the end\n");
for(i = 1;i<=count;i++)
{
scanf("%d\n",&a[i-1]);
}
printf("the original array is as follow:\n");
for(i = 1;i<=count;i++)
{
printf("%d ",a[i-1]);
}
reverse_array(a, count);
printf("the new array is as follow:\n");
for(i = 1;i<=count;i++)
{printf("%d ",a[i-1]);
}
}
进行书上练习2.6
习题总结: 熟悉十六进制与二进制之间的转换,并且了解什么叫做匹配位数。
- 表示字符串和代码: C语言中字符串被编码为一个null字符结尾的字符数组。每个字符串都由某个标准编码来表示,最常见的是ASCII字符码。
- 通过执行命令
man ascii
,你可以得到一张ASCII字符码的表。 - 布尔代数 常用运算符号:
与 :& 或 :| 非:~ 异或:^
进行书上练习2.8
-
位级运算:位向量按位进行逻辑运算,结果仍是位向量。位级运算的一个常见用法就是实现掩码运算,这里掩码是一个位模式,表示从一个字中选出的为的集合。
-
C语言中的移位运算: C语言标准并没有明确定义应该使用那种两类型的右移。对于无符号数据,右移必须是逻辑的。而对于有符号数据,算术的或者逻辑的右移都可以。
-
所有逻辑运算都可以用与、或、非表达(最大式、最小式),而与或非可以用“与非”或“或非”表达,所以,只要一个与非门,就可以完成所有的逻辑运算。
-
掩码是位运算的重要应用,对特定位可以置一 ,可以清零。
-
掩码是一个位模式,表示从一个字中选出的位的集合。
-
用位向量给集合编码,通过指定掩码来有选择的屏蔽或者不屏蔽一些信号,比如某一位位置上为1时,表明信号i是有效的;0表示该信号被屏蔽。
#include<stdio.h>
#define Max 10
int optarith(int x,int y);
void main()
{
int MAX;
int a[MAX];
int count,i;
printf("please enter the amount of numbers(no more %d):\n",MAX);
scanf("%d",&count);
printf("please enter any numbers as the end\n");
for(i = 1;i<=count;i++)
{
scanf("%d\n",&a[i-1]);
}
printf("the original optarith is as follow:\n");
for(i = 1;i<=count;i++)
{
printf("%d ",a[i-1]);
}
reverse_array(a, count);
printf("the new optarith is as follow:\n");
for(i = 1;i<=count;i++)
{printf("%d ",a[i-1]);
}
}
int optarith(int x,int y){
int x = 0;
x<<=5;
x-=t;
if(y<0)y+=7;
y>>=3;
return x+y;
}
- 整型数据类型
要用C99中的“long long”类型,编译是要用 gcc -std=c99。long long至少需要8个字节表示。
补码的利用寄存器的长度是固定的特性简化数学运算。想想钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要 一个加法器就可以实现所有的数学运算。
注意C语言中有符号数和无符号数的转换规则,位向量不变。
进行书上练习2.10、2.11
在虚拟机上进行代码编写,并回答问题。
- c语言中的移位运算右移
右移分为逻辑右移和算术右移。算术左移和逻辑左移没有什么区别。逻辑右移: 在左端补k个0,多用于无符号数移位运算算术右移: 在左端补k个最高有效位的值,多用于有符号数移位运算。
- 补码运算
补码的用法: 加法必须确定结果太大或者太小时,应该采取什么措施,两个数的w位补码之和与无符号数之和有完全相同的位级表示。大部分计算机使用同样的机器指令来执行无符号或者有符号加法。
- 根据阶码的值,被编码的值可分为三种:
一:规格化的值(当阶码字段不全为0或全为1时),阶码E = e-Bias
(e为无符号整数);偏置值 Bias = 2^(k-1)-1
;尾数M = 1+f
(小数字段frac的解释为描述小数值f,二进制小数点在小数字段最高有效位的左边)。
二:非规格化的值 (当阶码字段全为0时),E = 1-Bias;Bias = 2^(k-1)-1;M = f
。
三:特殊值 (当阶码字段全为1时),当小数域全为0时, 当s=1时,为-∞;当s=0时,为+∞;当小数域不全为0时,为NaN
-
向偶数舍入,也称为向最接近的值舍入,是默认的方式,方法是:将数字向上或者向下舍入,使得结果的最低有效数字是偶数。
-
注意:-1和UMax有同样的位表示——全1的串。数值0在两种表示方式中都是全0的串。
-
0扩展和符号扩展
零扩展:简单地在表示的开头添加0;
符号扩展:在表示中添加最高有效位的值的副本。
-
浮点数有科学计数法的基础就不难理解,IEEE标准754
-
浮点数运算的不精确性与舍入
IEEE浮点标准,float/double类型
IEE浮点标准: 用V=(-1)^s X 2^E X M 来表示一个数
-
符号:s决定这个数是正还是负。0的符号位特殊情况处理。
-
阶码:E对浮点数加权,权重是2的E次幂(可能 为负数)
-
尾数:M是一个二进制小数,范围为12-ε或者01-ε(ε=1/2的n次幂)
-
编码规则:单独符号位s编码符号s,占1位
k位的阶码字段exp编码阶码En位小数字段frac编码尾数M(同时需要依赖阶码字段的值是否为0)
单精度(float),k=8位,n=23位,一共32位;
双精度(double),k=11位,n=52位,一共64位。 一些位运算的常见技巧
0 ^ a = a
a ^ a = 0
a & (a - 1)可以消除最右边的一个1
位运算x & 0xFF生成一个由x的最低有效字节组成的值,而其他字节就被置为0。
Java是用的补码,0x7fffffff是最大正整数,0x80000000是最小的负数。和0x7fffffff按位与就是取绝对值了,然后那个按位或就是求负数。
可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a的奇偶性。
修改正负号就是按位取反再加一,也就是~x + 1
检验补码乘法是否溢出:
int p = x * y;
return !x || p / x == y;
教材学习中的问题和解决过程
问题: 教材中的练习2.34 对补码x[110]与y[110]的乘积结果[000100]的计算问题。
解决过程: 首先要了解补码乘法,然后进行了如下运算:
代码调试中的问题和解决过程
问题: 运行书上35页的两个代码,刚开始运行不了,然后自己加了一个主函数,还是有错误,错误信息如下:
解决过程: 在加了一个主函数后,定义了MAX常量,后成功运行:
代码托管截图
结对对象收获反馈
解决同伴在学习中遇到的问题:
问题: 为什么汇编中有两个分支呢?
解决过程: 第一个条件分支是&&表达式实现的一部分;如果对p为非空的测试失败,代码会跳过对a>0的测试。
其他(感悟、思考等,可选)
这次的博客是自己选一章觉得重要的内容进行再一次学习,所以这次的学习就要更加的深入,更加的详细,将上次遗留的问题进行解决,这次的收获也特别大,而且这次也和接伴对象一起学习,互相解决了彼此的问题。