[C指针]单链表:内存视角看待 addHead 函数的本质(内存

2019-04-19  本文已影响0人  AkuRinbu

学习笔记

[C指针]指针与结构体:完整源码 C语言 实现 单链表

https://www.jianshu.com/p/160a239086ae

addHead 源码

void addHead(LinkedList * list, void * data) {
    Node * node = (Node *) malloc(sizeof(Node));
    node->data = data;
    if(list-> head == NULL) {
        list->tail = node;
        node->next = NULL;
    } else {
        node->next = list->head;
    }
    list->head = node;
}

void initializeList(LinkedList * list) {
    list->head = NULL;
    list->tail = NULL;
}

addHead算法过程

先给节点分配内存,然后把传递给函数的数据赋给结构体的data字段。通过把data以void指针的形式传递,链表就能够持有用户想用的任何类型的数据了。接下来,我们检查链表是否为空,如果为空,就把尾指针指向节点,然后把节点的next字段赋值为NULL;如果不为空,那么将节点的next指针指向链表头。无论哪种情况,链表头都指向节点:

addHead 函数本质 内存示意图

addHead 本质.png

内存示意图说明

第一部分是左边,创建了一个局部变量node,对应于示意图中绿色部分;

第二部分是右边,动态分类了一个Node类型的内存空间,根据Node类型的定义可以知道,Node类型本质就是两个指针,一个void * data,一个 Node * next,指针本身的大小只与机器、编译器有关,而与指向的数据类型无关,因此不管是一个void * data,还是一个char * ptr ,在同一台机器、同一个编译器下,sizeof(data)sizeof(char) 的数值都代表的是指针的大小,在示意图中我假设指针大小是4字节,因此,datanext在连续的内存地址之下,表示为0x500、0x504这种;

第三部分,其实就是等于号 =,相当于示意图中的绿色箭头,把动态分配的内存空间首地址赋值给了node变量,即把0x500填到了绿色框内

node变量是函数局部变量,在函数执行完毕之后就不复存在,但是malloc分配的动态内存是一直存在的

首先,是语句右边的那个data,这是什么?这是函数的传入参数void addHead(LinkedList *list, void* data) {},前面说明过了,C语言是值传递,因此其实这个右边的data就是0x100,这条代码本质就是 node->data = 0x100;

然后再看,语句左边那个node->data是什么?前面说了,动态分配malloc内存 0x500 ~ 0x504 ~ 0x507这段连续的内存申请了内存空间,作为一个Node类型,换言之,如果你想要得到0x500这个数值,写的是 &node->data ,注意前面这个 &符号;

如果是 要修改0x500处的数据,就是用 node->data = 想写入的数据,注意,我们不是修改0x500,而是修改0x500处的数据,换言之,我们 想将0x100填入到0x500处

第一个地方,就是在函数addHead调用之前,最初那个Employee *samuel,这是一个指向Employee类型的指针,Employee *samuel = (Employee*) malloc(sizeof(Employee));,这同样是需要分三个部分:右边、左边、中间去看待的语句,并且我们知道真正存着那个有着name以及age的数据Employee 结构体是由malloc分配的,而0x100就是那个结构体的起始地址,在0x100开始那里才是存着真正的结构体;

第二个地方,当我们函数addHead的时候,的确有把0x100以值传递的形式发送给函数的传入参数的,但是无论是参数还是局部变量在函数执行完后不复存在了,可是在函数执行过程中,我们有明明确确地把0x100写到了0x500处,因此这里也存着一个0x100

上一篇 下一篇

猜你喜欢

热点阅读