当前位置 博文首页 > 难波儿万的博客:从计算机角度理解C语言指针(二)

    难波儿万的博客:从计算机角度理解C语言指针(二)

    作者:[db:作者] 时间:2021-06-14 21:46

    这一篇博文我们给内存分一下区。有同学会说,听说过给硬盘分区的没听过给内存分区的。其实,学习过Linux内核的同学肯定看到过有关页表的内容。这些讲起来太复杂还有什么虚拟内存等等内容更是无法理解,但是这些都不影响我们给内存分区。
    话说内存也不是什么神秘的东西,我感觉它就跟我们小学用的方格本差不多。唯一的区别就是我们这个方格本每一行都有32个格子,每个格子里只能放0或1。
    于是我们的程序就将这个叫内存的方格本分成了以下几个部分:
    1.程序代码区:这个区里面主要存放程序指令。
    2.栈区:这个区主要存放函数参数。
    3.堆区:这个区提供给程序猿自由使用,想怎么用就怎么用。不过用完了要还回来。
    4.静态存储区:这个区主要存储程序的全局变量。
    给内存分完区之后呢,我们来说说C语言的指针和内存的前世今生。
    我们都学过,指针就是地址。那是谁的地址呢?我们家的地址吗?还是硬盘的地址?这个地址有什么用呢?等等,一系列的问题应用而生。我想你已经猜到啦,对,指针就是内存的地址。它指示了我们标定的内存存储空间在方格本的第几行。为了方便编址,内存把方格本的第一页的第一行的第一个格编号为0直到最后一页的最后一行的最后一个格依次递加。下面我们将由浅入深逐步给出指针使用的各种方法,进一步深入理解指针和内存。

    1.变量、指针和指针变量

    int main()
    {
    	int a;
    	int *p;
    	int **pp;
    	printf("a1 = %d\n", a);
    	p = &a;
    	*p = 5;
    	printf("a2 = %d\n", a);
    	pp = &p;
    	**pp = 6;
    	printf("a3 = %d\n", a);
    }
    

    上面的代码段定义了3个变量和使用了两种符号。这两种符号分别是*和&,要想正确的理解指针,正确的理解这两个符号的使用是重点。所以我们要牢记一下三点:

    (1)运算符星在定义变量时在变量名前面使用表示定义的变量是个指针。
    (2)运算符星在给变量赋值时在变量名前面使用表示取出指针所指的内容。
    (3)运算符&表示取变量指针。
    运行上面的代码会输出以下结果:

    a1 = 4
    a2 = 5
    a3 = 6
    

    我们在我们的脑海中描绘一下变量a、p和pp在内存中是什么样子的就很容易理解上面的代码段同时输出这样的结果也显而易见。这里的三个变量我们一般有以下名字:

    a:int型变量它在内存中的地址为&a。
    p:int型指针变量,它的地址为&p。
    pp:指向int型指针变量的指针,它的地址为&pp。
    *p:取出指针p所指的int型变量。
    *pp:取出pp指针所指的int型指针变量。
    **pp:取出pp指针所指的int型指针所指的int型变量。
    

    到此我希望读者可以运行下面的程序,我将利用程序历程逐步描绘出变量在内存中的形态。

    int main()
    {
    	int a;
    	int *p;
    	int **pp;
    	p = &a;
    	*p = 5;
    	pp = &p;
    	**pp = 6;
    	printf("&a=%d, &p=%d, &pp=%d\n", &a,&p,&pp);
    	printf("p=%d, pp=%d, *pp=%d\n", p, pp, *pp);
    }
    

    运行结果为:

    &a=809374548, &p=809374552, &pp=809374560
    p=809374548, pp=809374552, *pp=809374548
    

    每次运行显示的数值不同,但是我们会发现以下关系

    *pp = p = &a;
    pp = &p
    结合上一个运行结果还有
    **pp = *p = a
    

    我们可以画出下面的内存图:
    在这里插入图片描述

    变量名大小(byte)地址
    a48093745485
    p4809374552809374548
    pp4809374560809374552

    结合程序运行结果和上面的图表,我们会很容易理解以下四条赋值语句:

    p = &a;
    *p = 5;
    pp = &p;
    **pp = 6;
    

    读者需要好好理解上面的几个例子,对理解指针有很大的好处。我的这篇文章C语言实现字符串split是字符指针、字符串和字符串指针数组很好的例子感兴趣的读者可以参考。