Lab 1 Exercise 4

  阅读关于C语言的指针部分的知识。最好的参考书自然是"The C Programming Language"。

  阅读5.1到5.5节。然后下载pointers.c的代码,并且编译运行它,确保你理解在屏幕上打印出来的所有的值是怎么来的。尤其要重点理解第1行,第6行的指针地址是如何得到的,以及在第2行到第4行的值是如何得到的,还有为什么在第5行打印出来的值看起来像程序崩溃了。

  答:

  首先编译运行文件pointer.c,得到如下结果:

  

  首先程序声明了3个重要的数组,指针

  int型数组--int a[4];    int类型指针--int *b = malloc(16);     int类型指针--int *c;

  打印的第一句:

    printf("1: a = %p, b = %p, c = %p\n", a, b, c);    

  其中:

    a输出的是数组a的首地址,0xbfb4bf84。  

    b输出的是指针b所指向的操作系统分配给它的空间的起始地址,0x8886008

    c输出的是未定义的指针变量c的值,0xb75d8255

  打印第二句之前,完成的操作:

    c = a;  让c指针和a指向同一个内存地址,0xbfb4bf84;

    for(i = 0; i<4; i++) a[i] = 100+i;   这个操作会让数组a的四个单元的值变为,100,101,102,103。

    c[0] = 200;   由于c和a指向同一个地方,c[0] = a[0] = 200;

    printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d,", a[0], a[1], a[2], a[3]); 所以打印第二句,第一个元素的值会是200.

  打印第三句之前,完成操作:

    c[1] = 300;

    *(c+2) = 301;

    3[c] = 302;

    分别代表访问数组中的值的三种不同的方法。由于c和a相同,所以它们也是在修改数组a的值。把a[1], a[2],a[3]全都被改变。printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d,", a[0], a[1], a[2], a[3]);

  打印第四句前,完成操作:c = c+1; 

    将指针c指向数组中下一个单元,即a[1]

    *c = 400

     修该a[1]值为400

     printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d,", a[0], a[1], a[2], a[3]);

  打印第五句前,完成操作

     c = (int *)((char *)c + 1);

    先把c强制转换为char类型指针,然后指针加1,此时c的数值应该也加1,由于之前c指向a数组中1号元素的起始地址,1号元素起始地址为0xbfb4bf88,之后加1,变为0xbfb4bf89。然后再把c强制转换回int类型指针,此时c所操作的地址为0xbfb4bf89~0xbfb4bf8c。

    *c = 500

    把地址地址为0xbfb4bf89~0xbfb4bf8c的值换为500,此时会影响原来数组a的1,2号元素。原来一号元素在内存中存放在地址0xbfb4bf88~0xbfb4bf8b处,存放的值为400,十六进制为0x00000190

     0xbfb4bf88  0xbfb4bf89  0xbfb4bf8a  0xbfb4bf8b

      90                 01                 00                00

     原来二号元素在内存中存放在地址0xbfb4bf8c~0xbfb4bf8f处,存放的值为301,十六进制为0x0000012D。

     0xbfb4bf8c  0xbfb4bf8d  0xbfb4bf8e  0xbfb4bf8f

       2D                 01                 00                00

    而现在c操作的地址为0xbfb4bf89~0xbfb4bf8c,并赋值500,十六进制为0x000001F4,所以内存单元变为

    0xbfb4bf88  0xbfb4bf89  0xbfb4bf8a  0xbfb4bf8b

     90                 F4                 01                00

    0xbfb4bf8c  0xbfb4bf8d  0xbfb4bf8e  0xbfb4bf8f

    00                 01                 00                00

    所以此时a[1]的值变为0x0001F490 = 128144, a[2]的值变为0x00000100 = 256.

    打印第六句前,完成操作:

    b = (int *)a + 1;

      这步操作会把b的值加1,由于b现在是int类型指针,所以数值上b的值增加4,所以b的值变为 0xbfb4bf84 + 0x4 = 0xbfb4bf88

    c = (int *)((char *)a+1);

      这步还是先把a转换为char型指针,然后加1,此时加1会让数值上只增加1,所以c的值变为 0xbfb4bf84 + 0x1 = 0xbfb4bf85

   当然运行在你的机器上,这些地址的值一定和我的不一样,但是原理是相同的。

MIT 6.828 JOS学习笔记8. Exercise 1.4的更多相关文章

  1. MIT 6.828 JOS学习笔记11 Exercise 1.8

    Exercise 1.8       我们丢弃了一小部分代码---即当我们在printf中指定输出"%o"格式的字符串,即八进制格式的代码.尝试去完成这部分程序. 解答: 在这个练 ...

  2. MIT 6.828 JOS学习笔记12 Exercise 1.9

    Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...

  3. MIT 6.828 JOS学习笔记13 Exercise 1.10

    Lab 1 Exercise 10 为了能够更好的了解在x86上的C程序调用过程的细节,我们首先找到在obj/kern/kern.asm中test_backtrace子程序的地址, 设置断点,并且探讨 ...

  4. MIT 6.828 JOS学习笔记9. Exercise 1.5

    Lab 1 Exercise 5 再一次追踪一下boot loader的一开始的几句指令,找到第一条满足如下条件的指令处: 当我修改了boot loader的链接地址,这个指令就会出现错误. 找到这样 ...

  5. MIT 6.828 JOS学习笔记5. Exercise 1.3

    Lab 1 Exercise 3 设置一个断点在地址0x7c00处,这是boot sector被加载的位置.然后让程序继续运行直到这个断点.跟踪/boot/boot.S文件的每一条指令,同时使用boo ...

  6. MIT 6.828 JOS学习笔记3. Exercise 1.2

    这篇博文是对Lab 1中的Exercise 2的解答~ Lab 1 Exercise 2: 使用GDB的'si'命令,去追踪ROM BIOS几条指令,并且试图去猜测,它是在做什么.但是不需要把每个细节 ...

  7. MIT 6.828 JOS学习笔记2. Lab 1 Part 1.2: PC bootstrap

    Lab 1 Part 1: PC bootstrap 我们继续~ PC机的物理地址空间 这一节我们将深入的探究到底PC是如何启动的.首先我们看一下通常一个PC的物理地址空间是如何布局的:        ...

  8. MIT 6.828 JOS学习笔记0. 写在前面的话

    0. 简介 操作系统是计算机科学中十分重要的一门基础学科,是一名计算机专业毕业生必须要具备的基础知识.但是在学习这门课时,如果仅仅把目光停留在课本上一些关于操作系统概念上的叙述,并不能对操作系统有着深 ...

  9. MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader

    Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c.但是在我们 ...

随机推荐

  1. JS事件-事件处理程序-笔记总结ing...

    html事件处理程序:缺点-行为与结构耦合<input type="button" onclick = "diaoyong();"> dom0级事件 ...

  2. BZOJ4650: [Noi2016]优秀的拆分

    考场上没秒的话多拿5分并不划算的样子. 思想其实很简单嘛. 要统计答案,求以每个位置开始和结束的AA串数量就好了.那么枚举AA中A的长度L,每L个字符设一个关键点,这样AA一定经过相邻的两个关键点.计 ...

  3. 怎样学习Java

    JAVA自学之路 一:学会选择 ,当你要走向社会的时候,就不要再把自己当成学生,不要把自己的将来交给别人,学会运用自己的眼睛去观察,去了解这个世界吧. 我讲一个通过招聘网站的观察方法: http:// ...

  4. QQ等级表

    什么是QQ等级呢? 2003年,腾讯公司推出了QQ等级制度 . 最早是以小时,来计算的,那段时间,绝大部分QQ用户都在挂QQ,之后就有不少媒体指责其浪费能源,在有关部门的介入下,腾讯公司将QQ等级变为 ...

  5. 面试题目——《CC150》递归与动态规划

    面试题9.1:有个小孩正在上楼梯,楼梯有n个台阶,小孩一次可以上1阶.2阶或者3阶.实现一个方法,计算小孩有多少种上楼梯的方式. 思路:第4个数是前三个数之和 注意:能不能使用递归,能不能建立一个很大 ...

  6. [Unity] 在协程中等待指定的毫秒

    先写一个静态类: /// <summary> /// 公用基础函数库 /// <remarks>作者: YangYxd</remarks> /// </sum ...

  7. Android 实现分页(使用TabWidget/TabHost)

    注:本文为转载,但该内容本人已亲身尝试,确认该方法可行,代码有点小的改动,转载用作保存与分享. 原作者地址:http://gundumw100.iteye.com/blog/853967 个人吐嘈:据 ...

  8. Java 内部类

    1.成员内部类 成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的.同时外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取. 2.局部内部类 ...

  9. JavaScript——基本的瀑布流布局及ajax动态新增数据

    本文用纯js代码手写一个瀑布流网页效果,初步实现一个基本的瀑布流布局,以及滚动到底部后模拟ajax数据加载新图片功能. 缺点: 1. 程序不是响应式,不能实时调整页面宽度: 2. 程序中当新增ajax ...

  10. POJ 1860(spfa)

    http://poj.org/problem?id=1860 题意:汇率转换,与之前的2240有点类似,不同的是那个题它去换钱的时候,是不需要手续费的,这个题是需要手续费的,这是个很大的不同. 思路: ...