ZUCC_计算机系统原理实验_实验五 位运算
浙江大学城市学院实验报告
一、实验目的:
了解高级语言中数据类型的转换和移位操作结果,从而能更好地理解指令系统设计和计算机硬件设计所需满足的要求和需要考虑的问题;
二、实验内容:
- 编写程序,完成实验讲义中的类型转换;
- 编写程序,测试xor_swap函数;
- 编写程序,测试并修改reverse_array函数;
三、实验步骤
1、编写程序,完成满足实验内容1的C语言表达式,并输出验证。
源代码:
#include <stdio.h>typedef unsigned char *byte_pointer;void show_bytes(byte_pointer start, int len) {int i;printf("0x");for (i = 0; i < len; i++)printf(" %.2x", start[i]);printf("\n");
}
void show_int(int x) {show_bytes((byte_pointer) &x, sizeof(int));
}int main(){int x = 0x12345678;//第一题show_int(x & 0xff000000);//第二题show_int(x & 0xff);//第三题show_int((x | 0xff) ^ 0xffffffff);//第四题show_int(x | 0xff);return 0;
}
运行结果:
2、编写程序,实现实验内容2中的类型转换,并解释程序运行结果。
源代码:
#include <stdio.h>typedef unsigned char *byte_pointer;void show_bytes(byte_pointer start, int len) {int i;printf("0x");for (i = 0; i < len; i++)printf(" %.2x", start[i]);printf("\n");
}
void show_int(int x) {printf("%d\t", x);show_bytes((byte_pointer) &x, sizeof(int));
}
void show_short(short x) {printf("%d\t", x);show_bytes((byte_pointer) &x, sizeof(short));
}
void show_float(float x) {printf("%f\t", x);show_bytes((byte_pointer) &x, sizeof(float));
}
void show_double(double x) {printf("%f\t", x);show_bytes((byte_pointer) &x, sizeof(double));
}
void show_unsigned_short(unsigned short x) {printf("%u\t", x);show_bytes((byte_pointer) &x, sizeof(unsigned short));
}
void show_unsigned_int(unsigned int x) {printf("%u\t", x);show_bytes((byte_pointer) &x, sizeof(unsigned int));
}int main(){//第一题short s = -12345;printf("Numb1\nint: ");show_int((int) s);printf("unsigned short: ");show_unsigned_short((unsigned short) s);printf("unsigned int: ");show_unsigned_int((unsigned int) s);printf("float: ");show_float((float) s);//第二题int x = 2147483647;printf("\nNumb2\nshort: ");show_short((short) x);printf("unsigned short: ");show_unsigned_short((unsigned short) x);printf("unsigned int: ");show_unsigned_int((unsigned int) x);printf("float: ");show_float((float) x);//第三题float f = 123456.789e5;printf("\nNumb3\ndouble: ");show_double((double) f);//第四题double d = 123456789e5;printf("\nNumb4\nfloat: ");show_float((float) f);//第五题short sm = -12345;unsigned short usm = -12345;printf("\nNumb5\nshort LM: ");show_short(sm << 2);printf("short RM: ");show_short(sm >> 2);printf("unsigned short LM: ");show_unsigned_short(usm << 2);printf("unsigned short RM: ");show_unsigned_short(usm >> 2);return 0;
}
运行结果:
对运行结果的解释:
第一题
- s(0xCFC7)由 short 转 int 没有精度损失,内存中数据仍按照原先的补码顺序保存。值得注意的是,这里由于使用小端存储,导致最后输出的16进制码与补码互逆
- short 转 unsigned short 符号位转换为数值位,有数据的改变。详细来说,由 0xCFC7 转为无符号值后,具体数值并未发生变化,但数值的解读发生了变化,将原来的符号位转化为数值位(原来15位–>16位),故转为十进制后为53191
- short 先转为 int 再转为 unsigned int,故 unsigned in t的机内码和 int 的机内码一致。具体在第二部转换过程中,同样发生了符号位转为数值位(原来31位–>32位),故转为十进制后为4294954951
- short 转 float 可能会产生精度损失。这里具体来说,符号位1,阶码127+13=140,尾数0x40E400,即0xC640E400(这里没有精度损失)
第二题
- x(0x7FFFFFFF)由 int 转 short 会发生截断,即只保留低4位(0xFFFF),故十进制为-1
- int 先转为 short 再转为 unsigned short,第二部分具体来说,即符号位转为数值为,故十进制为65535
- int 转 unsigned int ,即符号位转为数值为,故十进制为2147483647
- int 转 float 可能会产生精度损失。这里具体来说,符号位0,阶码127+30=157,尾数0x3FFFFFFF,即0x4EFFFFFF。但由于这里的 int 比较特殊,发生了舍入。在表示尾数时C99下之间认为是1.0(实际0.11…1),故阶码为127+31=158,尾数近似为 0,最后输出十六进制为0x4F000000
第三题
- f 由 float 转 double 不会出现问题,只是占位长度从4位变为8位。但赋值语句
float f = 123456.789e5;
本质是将 int 转为 float 再赋值。在这个过程中,发生了舍入,最终 f 的值是12345678848.0(0x5037F707)。故在转化为 double 后为12345678848.0,十六进制表示为0x4206FEE0E0000000
第四题
- d 由 double 转 float 可能会出现丢失精度的问题。同样,这里先由 int 转 double,但没有发生舍入,最终 d 的值为12345678900.0,十六进制表示为0x4206FEE0E1A00000。在第二部分过程发生了舍入,故转化为 float 后为12345678848.0,十六进制为0x5037F707。
第五题
- sm(0xCFC7)左移两位后为 0x3F1C,右移(由于是有符号数采用算术右移,最高位补符号位)两位后为0xF3F1。usm(53191,0xCFC7)左移两位后为 0x3F1C,右移(由于是有符号数采用算术右移,最高位补符号位)两位后为0x33F1。
3、编写测试程序test1.c,调用实验内容3中的xor_swap函数,并使用gdb工具调试程序,查看每步执行结果。
源代码:
#include <stdio.h>void xor_swap(int *x, int *y) {*y = *x ^ *y;*x = *x ^ *y;*y = *x ^ *y;
}int main(){int x = 1, y = -1;xor_swap(&x, &y);printf("x:%d\tY:%d\n", x, y);return 0;
}
调试过程截图展示:
调试准备
设置断点
查看每一步执行结果
- 初始化x,y
*y = *x ^ *y;
*x = *x ^ *y;
*y = *x ^ *y;
- 函数结束后
对每步运行结果的解释:
步骤 | *x | *y |
---|---|---|
初始 | a | b |
*y = *x ^ *y | a | a ^ b |
*x = *x ^ *y | a ^ (a ^ b) = (a ^ a) ^ b = b | a ^ b |
*y = *x ^ *y | b | b ^ (a ^ b) = (b ^ b) ^ a = a |
4、编写测试程序test2.c,调用实验内容4中的reverse_array和实验内容2中的xor_swap函数,并使用gdb工具调试程序,查看每步执行结果,回答实验内容4中的问题,并修改程序使之正确。
源代码:
#include <stdio.h>void xor_swap(int *x, int *y) {*y = *x ^ *y;*x = *x ^ *y;*y = *x ^ *y;
}
void reverse_array(int a[], int len) {int left, right = len - 1;for (left = 0; left <= right; left++, right--) {xor_swap(&a[left], &a[right]);}
}int main(){int c[3] = {1, 2, 3};reverse_array(c, 3);for (i = 0; i < 3; i++){printf("%d ", c[i]);}printf("\n");return 0;
}
调试过程截图展示:
调试准备
设置断点
查看每一步执行结果
- 初始化数组
- 进入for循环中出现问题的函数调用
- 初始化*x, *y
*y = *x ^ *y
*x = *x ^ *y
*y = *x ^ *y
- 函数结束后
对每步运行结果的解释:
- reverse_array 函数效果是对一个指定数组的指定部分从两端开始调用 xor_swap 函数,做到翻转数组的效果。但在 reverse_array 函数中的 for 循环中,由于传入 len 可能为奇数,将导致 left 和 right 指向同一个位置,运算结果为0,具体如下图
步骤 | *x | *y |
---|---|---|
初始 | a | a |
*y = *x ^ *y | a | a ^ a = 0 |
*x = *x ^ *y | 0 ^ 0 = 0 | 0 |
*y = *x ^ *y | 0 | 0 |
修改后的reverse_array代码:
void reverse_array(int a[], int len) {int left, right = len - 1;for (left = 0; left < right; left++, right--) {xor_swap(&a[left], &a[right]);}
}
修改后的程序运行结果:
四、思考题
1、无符号数和带符号整数的扩展操作方式是否相同?分别是如何进行的?
不同
- 对于无符号数,拓展位数即在高位补0;对于有符号数,拓展位数即在高位补符号位。
2、补码整数(如int型数)是否总能转换为等值的float类型数据?为什么?
不一定
- 例如 int 的有效数值最多可以由31位,而 float 的精度最多是23位,如果编译器转换时识别到精度损失将会对发生舍入操作,并伴有精度损失。
3、float型数据是否总能转换成等值的double型数据?为什么?
可以
- IEEE754下 float 的组成是1位符号位,8位阶码,23位尾数;double 的组成是1位符号位,11位阶码,52位尾数。显然转换时不会出问题。
4、长数被截断成短数后可能发生什么现象?为什么?
如果有效位数仍小于截断数,则大小不发生变化。
- 如果有效位数仍大于截断数,且短数为无符号数时,导致数值变小;如果是有符号数,会伴随着符号位的改变,于是这里会有三种情况
- 正常(这里只是针对数据属性没有发生变化,不针对具体数值)
- 正溢出(正数变负数)
- 负溢出(负数变正数)
5、C语言中移位操作规则与操作对象的数据类型有关吗?
右移有关,左移无关
- 左移都是在低位补0
- 右移对于无符号数,在高位补0;对于有符号数,在高位补符号位
6、左移2位和右移2位操作分别相当于扩大和缩小几倍?
扩大四倍,缩小四倍
ZUCC_计算机系统原理实验_实验五 位运算相关推荐
- 微型计算机系统原理及应用实验,微型计算机系统原理及应用实验报告 .doc
微型计算机系统原理及应用实验报告 微型计算机系统 原理及应用 ---实验报告--- 实验题目: 8255并行接口 学 院: 信息科学与技术学院 班 级: 姓 名: 学 号: 一.实验目的 学习和掌握8 ...
- java基本语句回文数实验_实验二 java基本数据类型与把持语句.doc
实验二 java基本数据类型与把持语句.doc 还剩 4页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 5System.out.println(num ...
- cmi编码实验_实验二 - 光纤通信系统线路码型CMI - 编译码实验 - 图文 -
实验二 光纤通信系统线路码型CMI 编译码实验 一.实验目的 1.了解线路码型在光纤传输系统中的作用 2.掌握线路码型CMI码的编译码过程以及电路实现原理 二.实验内容 1.验证符合光纤传输系统的线路 ...
- java实现三位数加减乘除_用Java位运算实现加减乘除四则运算
感谢博客:http://blog.csdn.net/itismelzp/article/details/49621741 提供的思路. 要用位运算来实现四则运算,不仅仅要知道&,|,~,^, ...
- JAVA PHP 按位异或运算_对php位运算^(按位异或)的理解
最近在看一些加密函数,其中总涉及到一些位运算,尤其是^(按位异或),经过多方查找资料,对^的理解深入,分享资料留作纪念! /* 手册资料: 位运算符 位运算符允许对整型数中指定的位进行置位.如果左右参 ...
- yxc_第一章 基础算法(三)_双指针算法位运算
一.双指针算法 1.双指针算法模板 2.AcWing 799 给定一个长度为 n 的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度. 输入格式 第一行包含整数 n. 第二行包含 n 个整 ...
- python 整数逆位运算_整数及其位运算
整数及其位运算 整数具有无限精度.有四种整数表示法:十六进制整数(0x 或 0X 开头),十进制整数,八进制整数(0o 或 0O 开头)和二进制整数(0b 或 0B 开头). # 十六进制 0x10 ...
- python左移右移位运算_荐Python : 位运算 —— 与、或、异或、左移、右移
Python : 位运算 -- 与.或.异或.左移.右移 位运算 位运算是把数字用 二进制 表示之后,对每一位上 0 或者 1 的运算.位运算共有 5 种运算:与.或.异或.左移.右移. 与.或.异或 ...
- ZUCC_计算机系统原理实验_大作业 bomb 破解
浙江大学城市学院实验报告 一.实验目的: 综合掌握程序的机器级表示以及汇编逆向调试过程. 二.实验内容: 二进制炸弹是作为一个目标代码文件提供给学生们的程序,运行时,它提示用户输入6个不同的字符串.如 ...
最新文章
- C# 汉字编码GB2312转换
- Git 常用命令,每条都很重要!
- mysql 报错注入 读文件_SQL注入-读写文件
- python从入门到实践django看不懂_Python编程:从入门到实践踩坑记 Django
- boost::fusion::reverse用法的测试程序
- RuntimeError: one of the variables needed for gradient computation has been modified by an inplace
- 数位DP CF 55D Beautiful numbers
- Cannot check for MySQL Daemon startup because of mysqladmin failure
- Yii2 behavior运用
- 【WebRTC---入门篇】(七)MediaStream
- [Unity]限制两个物体之间的距离
- MacOS Big Sur 11.5.1 (20G80) OC 0.7.1 / Cl 5138 / PE 三分区原版黑苹果镜像
- OpenSSL杂记(CA证书)
- 快递单号查询免费api接口(PHP示例)
- 关于GIS的一些感悟·思考
- LabVIEW,NI-DAQmx,LabWindows各个版本下载
- 通货膨胀与失业之间的短期权衡取舍 - 异想天开
- C语言自学(一)C语言基础
- 为项目加入第三方字体DS-Digital,并使用
- Fundamentals of Software Architecture:An Engineering Approach学习笔记
热门文章
- 川大计算机学院新生开学典礼,电子信息,自强不息 ——电子信息学院2018级本科新生开学典礼隆重举行...
- Kafka的监控指标
- 电子血压计方案提供模块芯片开发服务
- RINEX 2.11 观测值文件格式说明
- 正确区分二维动画和三维动画的区别!
- 诸侯安置 简单的递推
- RF自动化-RIDE(跑自动化注意事项)和(配置环境注意事项)
- uniapp的checkbox标签属性
- go语言中赋值出错:no new variables on left side of :=
- 链游知识01:同质化和非同质化资产标准是什么?