@[TOC]
# 一、相关概念的介绍
## 1、内存与地址
内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。换句话说,我们可以把计算机的内存看作是一条长街上的一排房屋。每座房子都可以容纳数据,并通过一个房号来标识。
![img](https://img-community.csdnimg.cn/images/40a8537753d74ece9434181fc2bc78c4.png "#left")
这个比喻颇为有用,但也存在局限性。计算机的内存由数以亿万计的位(bit)组成,每个位可以容纳值0或1。由于一个位所能表示的值的范围太有限,所以单独的位用处不大,通常许多位合成一组作为一个单位(比如字节,或者其2倍值4倍值),这样就可以存储范围较大的值。
比如上图我们通过每个字节来标识地址,也可以进一步扩大单位,如下图:
![img](https://img-community.csdnimg.cn/images/127969ab4214413288f1fc79623311f7.png "#left")
虽然一个字能占据的字节变多了,但是它仍然只占据了一个地址。
**因此,内存的特点如下:**
**_1.内存中的每个位置由一个独一无二的地址标识。
2.内存中的每个位置都包含一个值_**
## 2、&
“ & ”是一个用来取地址的单目运算符,在先前我们就已经和它接触
```c
#include <stdio.h>
int main(){
int a;
scanf("%d", &a);
printf("%d", a);
return 0;
}
```
**上述语句块含&语句的意义即为把标准输入中的值赋到变量a地址对应的值**
## 3、指针
```c
#include <stdio.h>
int main()
{
int i, *p; //定义指针
p = &i; //p的值代表i的地址,*p的值代表i的值
p = 0;
p = NULL;
p = (int *) 100; //对p进行赋值
return 0;
}
```
上述的**p被称为指针变量,i被称为整型变量**,二者关系如下:
![img](https://img-community.csdnimg.cn/images/bb58fabf59934a2da45909480bacf31b.png "#left")
(*为声明符,定义p时要写出,指针变量不是*p,是p)
## 4、指针的指针?
其实也就是指向指针的指针),举个例子:
```c
#include <stdio.h>
int main()
{
int a = 12;
int *b = &a;
int *(*c) = &b;
printf("%d %d %d",a,b,c);
return 0;
}
```
结果如下:
![img](https://img-community.csdnimg.cn/images/387b130a4d21414a8b16514685b6a716.png "#left")
说白了也没什么特别的,像上面一样理解就好了
# 二、指针的运算
## 1、基本运算
通过取地址运算符&和间接访问运算符 * 完成,比如说:
```c
#include<stdio.h>
int main(){
int a = 3, *p; /* 定义整型变量a和整型指针p */
p = &a; /* 把变量a的地址赋给指针p,即p指向a */
printf("a = %d, *p = %d\n", a, *p); /* 输出变量a的值和指针p说指向变量的值 */
*p = 10; /* 对指针p所指向的变量赋值,相当于对变量a赋值 */
printf("a = %d, *p = %d\n", a, *p);
printf("请输入a的值:");
scanf("%d", &a); /* 输入a */
printf("a = %d, *p = %d\n", a, *p);
(*p)++; /* 将指针所指向的变量加1 */
printf("a = %d, *p = %d\n", a, *p);
return 0;
}
```
输出结果如下:
![img](https://img-community.csdnimg.cn/images/39bc5f4e780e49d2b0cc9b5793859c36.png "#left")
**若添加语句“x = *p++”, 则p所指向a的值赋给x,再进行+1操作,让p不再指向a**
### 与数值加减
例:
```c
#include <stdio.h>
int main()
{
int a = 12;
int *b = &a;
*b=*b-1;
printf("%d %d",b,*b);
return 0;
}
```
结果如下:
![img](https://img-community.csdnimg.cn/images/69b96708386141be8b2a5e950b097426.png "#left")
## 2、指针间的运算
**赋值:**
```c
int a = 3, *p1, *p2; /* 定义整型变量指针p1和p2 */
p1 = &a; /* 使指针p1指向整型变量a */
p2 = p1;
```
**初始化:**
```c
int a;
int *p1 = &a; // 在定义指针p1的同时给其赋值,使指针p1指向变量a
int *p2 = p1; // 在定义指针p2的同时对其赋值,使p2和p1的值相同,都指向变量a
```
值得注意的是,指针变量**初值不能直接为数值**(如“int *p = 1000”),而int *p = 0; 是将指针变量初始化为**空指针**。(NULL)
**相减:**
```c
#include <stdio.h>
int main()
{
int a = 12;
int *b = &a;
int c=a-1;
int *d = &c;
char e = b-d;
printf("%d %d %d",d,b,e);
return 0;
}
```
结果:
![img](https://img-community.csdnimg.cn/images/33f6096be1d34b3db98bd121da1ea3aa.png "#left")
嗯,好,能减,不过两个指针得指向(或者同一数组中的)同一元素。
**关系运算:**基本同上,只要对着同一元素就嘎嘎用。
## 3、指针表达式(最晕的一集)
先定义两个变量:
![img](https://img-community.csdnimg.cn/images/1e8e499840b943c694561cb0ad21010f.png "#left")
对“++*ch”,"*ch++"等分别运行并查看相应值,发现它们存在非常大的差异,有些甚至显示错误,**主要原因**在于指针运算中指针表达式作为**左值右值**对于整个表达式有着举足轻重的影响,
不过随着进一步学习这一点应当会愈发清晰,故提前了解即可。
# 三、指针的应用
## 1、交换变量
代码如下:(主要还是要用第三者做桥梁)
```c
#include "stdio.h"
//交换两个变量的值
void swap2(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
int c = 3,d = 4;
printf("swap2交换c-d之前:%d,%d\n",c,d);
swap2(&c,&d);
printf("swap2交换c-d之后:%d,%d\n",c,d);
}
```
## 2、求最大最小值
代码如下:
```c
#include<stdio.h>
#define M 3
main()
{
int a[M],i;
int *max,*min;
for(i=0 ;i<M; i++)
{
scanf("%d",&a[i]);
}
//初始化max,min
max=a;
min=a;
/***** 将每个数组元素依次与max,min指向的数组元素比较,使max,min分别指向的最大、最小的数组元素 *****/
for(int j=0;j<3;j++){
if(*max<a[j]){
max=&a[j];
}
if(*min>a[j]){
min=&a[j];
}
}
/***** 通过指针变量max,min输出最大值和最小值 *****/
printf("min=%d\n",*min);
printf("max=%d",*max);
return 0;
}
```
## *3、指针常量
例如:
** _*(int *)100 = 25;_**
如果a存储于位置100,那么这条语句就强制把值25存储于a。但**用的很少**(因为这样做速度远不及&),唯一有用之处是你偶尔需要通过地址访问内存中某个特定的位置,它并不是用于访问某个变量,而是**访问硬件本身**。例如,操作系统需要与输入输出设备控制器通信,启动I/O操作并从前面的操作中获得结果。在有些机器上,与设备控制器的通信是通过在某个特定内存地址读取和写入值来实现的。(知道接口)
## 4、指针与数组
数组可以说是指针常量
int b[] 等价于 int *const b
**假设输入 "const int *p = &i;" 或者 "int const*p = &i;" i是无法通过p来修改的**
输入const int a[] = {1,2,3,4} 则该数组后续无法再变
**若*p指向num[0],那么*(p+1)指向num[1]**
关于动态内存分配和链表在结构体笔记补上