<注:个人学习总结,供网友参考学习,错误之处望不吝赐教,若对您有帮助,欣慰至极,转载注明并出处>
先要有堆区和栈区的概念,然后开始:
首先我们定义一个结构体和该结构体指针
typedef struct Lnod{ //定义节点
int data;//数据
struct Lnod *next;//指针
}LNode,*LinkList;// LNode 是节点指针,LinkList 是指向某个LNode的指针
//定义结束
LinkList L;
LinkList *L1;
L1=&L;
当执行完以上三条条语句后,思考下面变量是什么
-
LinkList L
- L
- &L
- *L
- &(*L)
- *(*L)
- & ((*L)) LinkList *L1
- L1
- &L1
- *L1
- &(*L1)
- *(*L1)
- & ((*L1))
用一个例子来说明问题,写出单链表的创建代码,并追踪打印其内存地址变化
#include <stdio.h>
#include <stdlib.h>
#include <malloc/malloc.h>
typedef struct Lnod{ //定义节点
int data;//数据
struct Lnod *next;//指针
}LNode,*LinkList;
void CreateList_L ( LinkList *L1, int n)
{
int i;
LinkList p,q;
*L1 = (LinkList)malloc(sizeof(LNode));
(*L1)->next = NULL;
p = *L1;
printf("L1:%x\n",L1);
printf("&L1:%x\n",&L1)
printf("*L1:%x\n",*L1);
printf("*L1:%d\n",(*L1)->data);
printf("&(*L1):%x\n",&(*L1));
printf("*(*L1):%x\n",*(*L1));
for (i=0;i<n;i++)
{
q = (LinkList)malloc(sizeof(LNode));
printf("请输入数据\n");
scanf("%d",&q->data);
q->next = NULL;
p->next = q;
p = q;
}
}
int main()
{
LinkList L;
CreateList_L(&L,3);
printf("L:%x\n",L);
printf("&L:%x\n",&L);
printf("*L:%d\n",(*L).data);
printf("&(*L):%x\n",&(*L));
// printf("%i",(*(*L)));
}
输出结果为
得出以下示意图:
注: 箭头上的为该变量或者堆区的地址
可以通俗的解释为: L指针变量存储了堆区1054e0这个地址,所以它指向这个堆区,而通过函数调用(L1 =&L),将L的变量地址赋值给了L1,这样是 L1 存储了 L的变量地址,所以 *L1指向L,而L本身是指针,所以 L1实际是一个指向指针的指针(二级指针)。除了定义时外,表示取该指针指向的内容,&表示取地址,所以可知:
-
LinkList L
- L 指针L指向的某个LNode的内存地址的值 (存储在栈区)
- &L 指针L自己在栈区的地址的值 (存储在栈区)
- *L 指针L指向的内存地址中的内容(是某个LinkList结构体,存取在堆区)
- &(*L) 指针L所指向的内存地址的值
- *(*L) //编译不通过
- & ((*L)) //编译不通过 LinkList *L1
- L1 指针L1指向某个LinkList指针本身的存储地址 (存储在栈区)
- &L1 指针L1本身存储地址
- *L1 指针L1所指向的内容,是某一个LinkList指针
- &(*L1) 指针L1指向的一个LinkList指针本身的存储地址,即指针指向的那个指针的地址
- *(*L1) 指针L1指向的一个LinkList所指向的一个LNode,即指针指向的那个指针所指向的内容
-
&((*L1)) 指针L1指向的一个LinkList所指向的那个LNode的地址(堆区),即指针指向的那个指针所指向的内容的内存地址
以上结合Charm图和实际输出便很好理解了