《MIT 6.828 Lab 1 Exercise 4》实验报告
本实验链接:mit 6.828 lab1 Exercise 4。
题目
Exercise 4. Read about programming with pointers in C. The best reference for the C language is The C Programming Language by Brian Kernighan and Dennis Ritchie (known as 'K&R'). We recommend that students purchase this book (here is an Amazon Link) or find one of MIT's 7 copies.
Read 5.1 (Pointers and Addresses) through 5.5 (Character Pointers and Functions) in K&R. Then download the code for pointers.c, run it, and make sure you understand where all of the printed values come from. In particular, make sure you understand where the pointer addresses in printed lines 1 and 6 come from, how all the values in printed lines 2 through 4 get there, and why the values printed in line 5 are seemingly corrupted.
解答
题目包括两部分:一是阅读《The C Programming Language》,二是运行pointers.c文件并理解其输出。
一、阅读《The C Programming Language》
已阅读完成《The C Programming Language》第5.1~5.5节的内容,并输出学习笔记。
二、 运行pointers.c文件并理解其输出
void f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
运行前我先写出自己对6个输出的猜测,运行后发现第1和第5个输出猜错了,其他4个猜对了。
第1个输出是打印3个局部变量的地址,我以为a,b,c的内存地址是紧挨着的,因此猜测b的地址比a的大16,c的地址比b的大4.运行结果却是:
1: a = 0x7ffc06689160, b = 0x556fb6ccc260, c = 0xf0b2ff。问题出在哪里?后来我才意识到指针的值实质上是它所指向的内存地址,而不是指针本身的内存地址。要想获取指针本身的内存地址,要在指针前面加上取址符号&。于是我对指针b和c加上&后再编译运行,结果为1: a = 0x7ffef6a4c1c0, &b = 0x7ffef6a4c1b0, &c = 0x7ffef6a4c1b8。可见变量a,b,c的内存地址是在栈内紧挨着的。注意由于我用的是64位系统,指针是用8个字节存储。不过有个问题没想明白:定义局部变量的顺序是a -> b -> c,但在栈中的地址从小到大却是b -> c -> a,为什么不一致?有待研究。第2个输出是直接对数组元素赋值后再打印数组内容,很简单。此处的目的应该是展示最直接的访问数组元素的方式:数组名加下标。
第3个输出是使用各种方式对数组元素赋值后再打印数组内容,也很简单。值得注意的是
3[c]的写法居然也是合法的,因为C编译器直接将其转换成*(3+c)。第4个输出展示了:对指向数组的指针加上(或减去)N,相当于访问数组中当前元素的后面(或前面)第N个元素。
第5个输出有点意思,指针c原来指向a[1],接下来被修改为指向a[1]的第2个字节,然后再修改c的值,这时a[1]和a[2]的值都会受影响。修改前a[1]=0x00000190, a[2]=0x0000012b. 而500=0x000001f4,因此我猜测修改后a[1]=0x00000001,a[2]=0xf400012b.运行结果却是a[1]=0x0001f490, a[2]=0x00000100. 为什么?原来是字节序在作怪!我电脑是小端字节序,而我按照大端字节序来做了。
第6个输出表明指针加减某个整数对应的内存偏移量取决于指针的类型。
《MIT 6.828 Lab 1 Exercise 4》实验报告的更多相关文章
- [操作系统实验lab3]实验报告
[感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...
- Ucore lab1实验报告
练习一 Makefile 1.1 OS镜像文件ucore.img 是如何一步步生成的? + cc kern/init/init.c + cc kern/libs/readline.c + cc ker ...
- ucore操作系统学习(三) ucore lab3虚拟内存管理分析
1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...
- 《ucore lab3》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1:给未被映射的地址映射上物理页 题目 完成do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页.设置访问权限的时候需 ...
- 《ucore lab1 exercise5》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...
- 《ucore lab8》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...
- 《ucore lab7》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...
- 《ucore lab6》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...
- 《ucore lab5》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...
- 《ucore lab4》实验报告
资源 ucore在线实验指导书 我的ucore实验代码 练习1:分配并初始化一个进程控制块 题目 alloc_proc函数(位于kern/process/proc.c中) 负责分配并返回一个新的str ...
随机推荐
- Appium自动化测试教程-自学网-安卓模拟器
安卓模拟器: 夜神模拟器安装配置 下载地址:https://www.yeshen.com 开启VT VT是什么?为什么要开启VT? VT,全称是Virtualization Technology,即是 ...
- UDP广播,组播服务器
广播 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ ...
- 51nod 1076
* 无向图的割边将图分为不连通的两部分 * 对于是否有不想交的两条路径将s -> t 相连 * 只需判断是否处于同一部分 * Tarjan即可 #include <bits/stdc++. ...
- 串结构练习——字符串连接(SDUT 2124)
Problem Description 给定两个字符串string1和string2,将字符串string2连接在string1的后面,并将连接后的字符串输出. 连接后字符串长度不超过110. Inp ...
- nodejs基础(管道、流)实现:复制、压缩、加密、解压,解密,写入文件
stream流 都是events.EventEmitter的一个实例,都可以来创建自定义事件(也就是说,流是一个事件的实例) 在nodejs中 对http的请求与响应都是用流来实现的,请求就是一个输入 ...
- .net Core使用 MongoDB
1.安装mogodb windows版本下载地址:https://www.mongodb.com/download-center/v2/community 查看mongod.conf文件,找到绑定的I ...
- W tensorflow/core/platform/cpu_feature_guard.cc:45]
W tensorflow/core/platform/cpu_feature_guard.cc:] The TensorFlow library wasn't compiled to use SSE3 ...
- vue 路由跳转记住当前页面位置
从列表页面跳去详情页面, 在列表页面的生命周期:deactivated 中把当前的scrollTop位置存下来,可以存在localstorage中,也可以存在vuex中, 从详情页面返回列表页面:a ...
- 黑马vue---40、结合Node手写JSONP服务器剖析JSONP原理
黑马vue---40.结合Node手写JSONP服务器剖析JSONP原理 一.总结 一句话总结: 服务端可以返回js代码给script标签,那么标签会执行它,并且可带json字符串作为参数,这样就成功 ...
- centos7 设置 tomcat 开机自启
1.创建文件 # vi /etc/systemd/system/tomcat.service [Unit] Description=Tomcat8540 After=syslog.target net ...