本文对CSAPP学习第二章《信息的表示与处理》中的编程案例实践和大实验DATALAB进行汇总小结。
第二章内容主要包括:
- 数据在内存中的表示方式
- 布尔运算——位运算(~ & | ^)、逻辑运算(! && ||)
- 整数的表示方法与运算
- 浮点数的表示方法与运算
实践一对应1;实践二对应2;整数和浮点数的表示与运算主要以数学角度阐述,在DATALAB中有所涉及。
实验环境:Win10利用VMware创建的Ubuntu虚拟机。
实践一:Linux系统下int型、float型、double型、指针数据在内存中的表示方式。
实践目的:对内存中的数据保存格式有个初步直观的概念,结合32位机器和64位机器的差异、大端表示法和小端表示法的差异,在自己的机器(操作系统)上了解Linux-64位机的数据存储格式。
创建文本文档,输入如下代码,将文档重命名为 bytes.c 。
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len){
for(size_t i = 0; i < len; ++i)
printf(" %.2x", start[i]);
printf("\n");
}
void show_int(int x){
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_float(float x){
show_bytes((byte_pointer) &x, sizeof(float));
}
void show_double(double x){
show_bytes((byte_pointer) &x, sizeof(double));
}
void show_pointer(void *){
show_bytes((byte_pointer) &x, sizeof(void *));
}
void test_show_bytes(int val){
int ival = val;
float fval = (float)val;
double dval = (double)val;
int *pval = &val;
show_int(ival);
show_float(fval);
show_double(dval);
show_bytes(pval);
}
int main(){
int val = 12345;
test_show_bytes(val);
return 0;
}
在文件下打开终端,用 gcc 指令编译、运行 .c 文件。
第一行指令编译 .c 程序 并生成可执行文件(命名为bytes);
第二行指令执行文件 bytes 。
Linux-64位机上,整型和浮点型数据以小端方式保存;指针数据为64位(与系统的虚拟内存允许的最大寻址空间一致),不同机器的地址分配方式不同,因而指针数据也是不同的,甚至一台机器中执行同样的程序时,地址分配也会不同:
实践二:不使用额外空间,将一个数组逆序。
实践目的:体验位运算中的“加法逆元”。位运算有很多巧妙的tricks,这只是其中一个有趣的例子。
void inplace_swap(int *x, int *y){
*x = *x ^ *y; //*x = a^b ; *y = b
*y = *x ^ *y; //*x = a^b ; *y = a^b^b = a
*x = *x ^ *y; //*x = a^b^a = b ; *y = a (^运算遵循交换律)
}
void reverse_array(int a[]; int len){
int first, last;
for(first = 0, last = len - 1; first < last; ++first, --last)
inplace_swap(&a[first], &a[last]);
}
注意:第二个函数中的循环条件不能是 first <= last ,否则当数组长度为奇数时,中间的数会经过^运算变为0。
DATALAB
LAB网址:http://csapp.cs.cmu.edu/3e/labs.html
PART1-实验环境配置
Linux中使用 wget + URL 指令下载:
使用 tar -xvf file_name.tar 进行解压:
这里有一个问题,下载的程序设置的编译器是32位,在终端使用很多指令都会出错,如指令make:
解决方法:打开文件Makefile,直接将 CFLAGS = -O -Wall -32 改为 CFLAGS = -O -Wall -64 。
(这个问题困扰了我很久,最终在知乎一个专栏上找到解决方法,感谢大佬的分享!!!)
(附上链接: