顿悟 - 对指针的理解

  接触C语言也快两年了,对指针的理解也一直迷迷糊糊,虽然能用指针解决一些问题,但是对于复杂一点的问题,如两级指针的运用,却感到力不从心,无法做到运用自如,两下子就被搞得晕乎乎的了,究其原因,还是对于指针的理解不深刻导致的。

  今天在回顾链表的创建时遇到了一些想不通的情况,于是下了“不到黄河心不死”的决心要把指针弄懂,弄透,终于对指针的理解有了质的提高,发现我以前对指针的理解大错特错了,于是将今天所悟记录下来,方便日后回顾。

  如下:

  typedef struct _node

  {

    int data;

    struct node* next;

  }node;

函数CreateList(node * head)为创建链表的函数;

  在main()中有如下语句:

  int main()

  {

    node *head = 0x1111;(这里仅为举例)

    CreateList(head);

    print(head);

  }

  但是创建并不成功,什么也打印不出来,在CreateList中,我企图为head开辟空间存入数据,函数逻辑是没有错的,但是却没得到预期结果,我感到很奇怪。我开始是这样认为的,主函数的head的值比如是0X1111(当然这里是NULL),以值传递的方式传入CreateList,那CreateList中head的值仍然是0X1111,在CreateList中为head开辟了内存,也就是为地址0X1111开辟了内存,然后存入数据,既然main函数中head的值也是0X1111,那么当调用CreateList后,main函数中的head也指向了在CreateList中开辟的内存,自然就创建好了链表,但是为什么不行呢?后来经过思考,也是冥冥中恍然大悟,我对指针的理解千错万错就在这里。如 int i = 100; int *p = &i;这样p就指向了i,假设i的地址是addr1,那么p的值也是addr1,接下来如果执行p = new int;我的理解是系统为p开辟了新的内存,也就是为地址addr1开辟了新的内存,地址addr1指向这块内存(现在想起来这种想法误导我很深啊!怪不得以前觉得一些使用指针得到的结果很奇怪),后面我通过打印p的值发现p的值居然不是addr1,而是另外一个值addr2,我仿佛糟了晴天霹雳,呵呵,这真是个伟大的发现,就是这个addr2让我对指针的理解如梦方醒。现在我来概括一下:开始我一直以为int *p = new int 这个语句不是简单的变量赋值,而是为p的值addr(某个地址)开辟一片内存,让p的值addr指向这个新开辟的内存,无论后面执行多少次这个语句,其作用不过是让p的值addr指向新开辟的内存,而p的值addr永远不会变,是1就一直是1,是2就一直是2,这是我以前的想法。现在的理解是:int *p = new int这个语句就是简单的赋值,如果p原来的值为addr1,那么将new int后的值为addr2赋给p,于是p的值就变成了addr2,自然就指向了新内存(天哪,多么简单,不就是变量的赋值吗?真不知道为什么以前想那么复杂),而不是为p原来的值addr1开辟新内存.

  现在回过头来看这个例子,当执行完main()后,main()中的head仍然为0x1111,虽然在CreateList中head的初始值也是0x1111,但当在CreateList中执行开辟如new,malloc之类的语句时,不是我开始想的那样为地址0x1111开辟地址,CreateList中head的值已经不再是0x1111,新开辟的内存不是由0x1111指向的,所以在main()中的head是没有指向新开辟的内存,它原来指向哪里,现在还指向那里,它原来为空,现在还为空,因为它的地址仍然是0x1111.

  正确的做法是:

  CreateList(node ** head);

  

int main()

  {

    node *head = 0x1111;(这里仅为举例)

    CreateList(&head);

    print(head);

  }

  这样,调用CreateList(node ** head)后,main()中head的值才不为0x1111,而是指向新开辟的内存的值,也许是0xxxxx,呵呵,管它是什么,不重要,反正不是0x1111.

  这个对指针认识的过程有很多浅显的地方,让大牛看了觉得可笑,但是我只是记录学习过程中的领悟,方便以后回顾,也是记录我这个菜鸟的成长路程,学习路上总有写可笑的事情。

  Good night!!

时间: 2024-10-11 04:41:06

顿悟 - 对指针的理解的相关文章

【C语言学习】指针再理解(一)

★内存和地址 内存的基本单位是字节,那么内存就可以按字节进行编址,就是给组成内存的所有连续的字节安排地址.其中一个最恰当的比喻就是房子与门牌号,假设有20间连续的房子,从最左边(或者左右边)开始分配门牌号1~20,给内存中字节分配的地址就相当于门牌号,字节就相当于房间.字节的容量只能存储一个字符.那么,内存是如何存储比字符更大的数据呢,比如:整型数据.浮点型数据? ★更大的内存单元 为了存储更大的数据,就会把两个字节或者跟多的字节合在一起组成更大的内存单元.比如内存可以以"字"为单位来

Delphi指针运用理解

现在是面向对象漫天飞的年代了,大家都在在谈面向对象编程.Java对指针“避而不谈”,C#虽然支持指针运用,但是也淡化处理. 然而,指针还是好完全掌握为妙,省得在开发过程碰钉子,至于对指针的运用在于开发人员的存乎于心,运用得当.指针运用的不好,不要怪开发语言及其机制.下面谈到的是在Delphi中指针的运用,至于其他语言,指针的思想是相通的. 指针是一种数据类型,和编程语言中其它的类型一样,是一种类型的区分,比如 Integer 是带符号的整型,在32位X86机中,是用4个字节表示,而指针也是用4个

说说对C语言指针的理解

指针困扰了无数学习编程的人,或许你的老师会告诉你,指针比较难学. 然而,不要被吓到,本宝宝就是当时被老师的话唬住所以学习指针那章的时候都没心情听课.(说得像讲别的内容时我听了似的,just kidding) 导致了学习链表的时候各种卧槽. *************************** 基本介绍 ************************** 程序中数据的使用往往是以变量的形式出现,每个变量都对应若干存储单元,变量的值存储在存储单元中,通过对变量的引用和赋值就可以使用或修改存储在存

JavaScript——对this指针的理解

在我们声明一个函数时,每个函数除了有定义时的parameters(形参),自身还会有额外的两个参数,一个是this,一个是arguments(实参).arguments就是函数实际接受到的参数,是一个类数组.arguments我只做个简略的介绍,重点我们放在this指针上. 在面向对象变成中,this十分重要,它的值取决于调用的模式.而在JavaScript中,一共有4中调用模式:方法调用模式.函数调用模式.构造函数调用模式.apply调用模式. 方法调用模式 当一个函数是作为一个对象的属性时,

对于C语言中数组名是指针的理解

我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3,4}; for(int i=0;i<4;i++) {  cout<<*(a+i);//*(a+i)和a[i]是等价的.  cout<<endl; } return 0;} 但是看下面这个代码 #include<iostream>using namespace std;

C/C++学习笔记----指针的理解

指针是C/C++编程中的重要概念之一,也是最容易产生困惑并导致程序出错的问题之一.利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯:指针能够灵活的操作内存,合理的操作内存能够使程序更高效. 1.指针的概念 本质上讲指针也是一种变量,普通的变量包含的是实际的数据,而指针变量包含的是内存中的一块地址,这块地址指向某个变量或者函数,指针就是地址.指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据. 2.指针的内容 指针的内容包含4部分

c语言函数指针的理解与使用

转载:http://www.cnblogs.com/haore147/p/3647262.html 1.函数指针的定义 顾名思义,函数指针就是函数的指针.它是一个指针,指向一个函数.看例子: A) char * (*fun1)(char * p1,char * p2); B) char * *fun2(char * p1,char * p2); C) char * fun3(char * p1,char * p2); 看看上面三个表达式分别是什么意思? C)这很容易,fun3是函数名,p1,p2

如何保存指针地址 理解指针的指针

有这样一个问题就是如何使用一个整数保存一个结构体或类以及其他类型的指针,这种需求在不同语言之间调用是存在的,例如有一个结构体A: struct A { char item1; int item2 }; 需要使用一个整数b,需要用b保存这个结构体指针的地址(struct A* a = new A),使得b的值就是a的指向的地址,你可能会想直接b = a就可以了,但是编译器都不会答应.因为类型不同,一个是整数一个是指向struct A的指针. 正确的方式如下: unsigned int b = 0;

Go语言中地址传递及指针的理解

在学习指针时遇到一个问题,在网上贴出后,得到很多前辈的指导和耐心解答,在此表示感谢,因此整理了此篇文章. 第一次实验,代码如下: type Student struct { Name string } func remove(stu *Student) { fmt.Printf("2----%v\n", stu) stu = nil fmt.Printf("3----%v\n", stu) } func main() { stu := &Student{&q