zoukankan      html  css  js  c++  java
  • MIT 6.828 JOS学习笔记8. Exercise 1.4

    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 ", 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

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

     

  • 相关阅读:
    POJ 3140 Contestants Division (树dp)
    POJ 3107 Godfather (树重心)
    POJ 1655 Balancing Act (树的重心)
    HDU 3534 Tree (经典树形dp)
    HDU 1561 The more, The Better (树形dp)
    HDU 1011 Starship Troopers (树dp)
    Light oj 1085
    Light oj 1013
    Light oj 1134
    FZU 2224 An exciting GCD problem(GCD种类预处理+树状数组维护)同hdu5869
  • 原文地址:https://www.cnblogs.com/fatsheep9146/p/5216735.html
Copyright © 2011-2022 走看看