### [指针](https://www.kancloud.cn/alex_wsc/jni/2019192)
![](https://img.kancloud.cn/0a/90/0a90dae3f3546f26b6e00f884f92104e_1112x837.png)
```
#include <stdio.h>
int main ()
{
int var_runoob = 10;
int *p; // 定义指针变量
p = &var_runoob;
printf("var_runoob 变量的地址: %p\n", p);
return 0;
}
```
输出结果
~~~
var_runoob 变量的地址: 0x7ffecfbfcd54
~~~
![](https://www.runoob.com/wp-content/uploads/2014/09/c-pointer.png)
#### **链表数据结构**
指针的最大作用是构造数据结构,使用指针将不连续的内存空间连接到一起,如:最简单的数据结构链表,它是非连续、非顺序的存储结构,有一些节点组成,节点当中包括数据域和指针域,数据域用来存储相应的数据,指针域用来存储下一个节点的地址,这些节点通过指针相连之后,就形成了链表。如节点1和节点2连接,就是将节点1的next域中存储节点2的地址,通过这个地址就可以从节点1找到节点2
![](https://img.kancloud.cn/cb/41/cb410b213320c9ca162ad920b469b182_1703x662.png)
```
#include <stdio.h>
#include <stdlib.h>
//链表节点的数据结构
struct ListNode
{
int val;//数据域
struct ListNode *next;//连接下一个节点的指针
};
void main() {
//创建5个链表节点 a, b, c, d, e
struct ListNode a, b, c, d, e;
//将它们赋值为1、2、3、4、5
a.val = 1;
b.val = 2;
c.val = 3;
d.val = 4;
e.val = 5;
//通过next指针,将它们依次相连
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = NULL;
struct ListNode *head=&a;
while (head)
{
//循环打印链表中节点的值、节点的地址和节点的next指针
printf("val = [%d] address=[%p] next=[%p]\n",head->val,head,head->next);
head = head->next;
}
system("pause");
}
```
输出结果
![](https://img.kancloud.cn/3f/96/3f964a5e5a2c7b014dc43646e40d1fd9_858x463.png)
从打印结果可以看出:**val的值为1到5,next指针当中存储了下一个节点的地址,最后一个节点的next指针为空,这样就实现了独立节点的创建、链接和遍历**。
#### **指向指针的指针**
一般多层指针不常用到(数组会用到二级指针,三级指针很少用到),指针最常见的用途还是构造数据结构和操作内存。动态内存分配给二维数组。
如图所示,一般我们用一个矩形来表示一个标量
![](https://img.kancloud.cn/b4/36/b43640361cfd552043e63f2eec550a71_477x382.png)
多层指针的演示
![](https://img.kancloud.cn/52/f4/52f412c1589041314505826cb4229b67_1386x240.png)
```
#include <stdio.h>
#include <stdlib.h>
void main() {
int number = 5;//声明number,赋值为5
int *ptr1 = &number;//将指针ptr1指向number,赋值为number的地址
int **ptr2 = &ptr1;
int ***ptr3 = &ptr2;
printf("number的地址:%#x\n", &number);
printf("number的值:%d\n", number);
printf("\n");
printf("ptr1的地址:%#X\n", &ptr1);
printf("ptr1的值:%#X\n", ptr1);
printf("ptr1指向的变量的值:%d\n", *ptr1);
printf("\n");
printf("ptr2的地址:%#X\n", &ptr2);
printf("ptr2的值:%#X\n", ptr2);
printf("ptr2指向的变量的值:%#X\n", *ptr2);
printf("\n");
printf("ptr3的地址:%#X\n", &ptr3);
printf("ptr3的值:%#X\n", ptr3);
printf("ptr3指向的变量的值:%#X\n", *ptr3);
printf("\n");
system("pause");
}
```
输出结果
```
number的地址:0xbffe9c
number的值:5
ptr1的地址:0XBFFE90
ptr1的值:0XBFFE9C
ptr1指向的变量的值:5
ptr2的地址:0XBFFE84
ptr2的值:0XBFFE90
ptr2指向的变量的值:0XBFFE9C
ptr3的地址:0XBFFE78
ptr3的值:0XBFFE84
ptr3指向的变量的值:0XBFFE90
```