目录
一,什么是指针?
C语言中变量是容器,可看作装酒的酒杯,只不过装的不是酒,是各种内存。
而指针是一种特殊的变量:因为是变量,所以能保存具体值;特殊之处就在于指针保存的值是内存的地址;
内存地址:计算机中每个存储单元都有编号,这些编号就是内存地址。
需要清楚的事实:程序中一切元素都存储在内存中,因此可以通过访问地址来使用元素,而指针的作用就是作为一个容器存储地址,对地址的一切操作都要通过指针来完成。
如何获取具体地址:
通过取地址操作符——& 来获得。
&的作用:可以获取变量,数组,函数的地址。
确定一个具体的地址是通过:确定起始地址+长度来确定。
各种数据类型长度:
指针定义语法:type* pointer;
type 数据类型,决定访问内存的长度;
注意:指针的类型统一只占4字节或8字节。
* 指针访问操作符,标志为指针变量。
pointer 变量名,遵循C语言命名规则。
int main()
{
char* pChar;
int* pInt;
double* pDouble;
return 0;
}
int var=0 ; //定义变量var初始值为0;
int* pvar=NULL ; //定义pvar的所占地址的开始值为NULL,即0值;
pvar = &var; //把var变量的地址赋值给pvar.
*pvar = var; //把var的值赋值给*pvar.
归类:var,*pvar为int类型变量;
pvar,&var为变量地址;
二,指针的注意事项
type* 类型的指针只能存储type类型变量的地址;
禁止不同类型的指针相互赋值;
通过指针参数:
——能够实现函数交换变量的值;
——能够从函数中"返回"多个值;而return只能返回一个值;
三,指针与数组
在数组中,元素本身就是地址。所以数组名虽然不是指针,但可以看作指针;
这样的话,数组元素就可以直接对指针赋值,数组名也可以对指针赋值。
数组名可直接看作一个指针,表示数组中0元素的地址;
a等价于&a[0]
不过&a则表示整个数组的地址,虽然值和0元素的地址一样,但意义不同。
——&a代表数组地址,类型为:int(*)[ ]
——a代表数组0号元素地址,类型为:int*
看得出两者类型不一致,所以不能相互赋值。
所以定义:
指向数组的指针:int (*pName)[ ] = &a;
指向数组0号元素的指针:int* pName = a;
当指针指向数组元素时,可以进行指针移动。
int a[] = {1, 2, 3, 4, 5};
int* pa = a;
p = p + 1; //现在p指向了下一个元素。
指针与字符串:
字符串其实就是特殊的数组,特殊在于该数组最后元素的值为'\0'。
字符串常量就是一种char*类型,一种指针类型,存在的地址为全局变量区。
使用字符串的时候,其实就是在使用char*类型的数据。
例如用&对"Hello"取地址,结果为"Hello"在全局变量区的起始地址。
"Hello"可看作一个地址;
*"Hello"看作从这个地址中取值;
四,指针与函数
函数的本质就是内存中的一段代码:
函数的类型,函数类型由返回类型和参数类型列表决定:
函数名就是函数体代码的起始地址;
通过函数名调用函数,本质为指定具体地址的跳转执行
因此,可以通过指针,保存函数入口地址;
函数指针:
对于函数为type func (type 1, type 2)格式的
指向该函数的指针为:type (*pfunc)(type 1, type 2) = func/NULL;
值得注意的是,函数指针只是单纯的保存函数的入口地址,所以只能通过函数指针调用目标函数。
当数组作为参数时:
当数组作为参数,会退化成为一个指针;
int demo(int arr[ ],int len) → int demo(int* arr, int len).
因此,不包含数组实参的长度信息。使用数组名调用时,传递的是0号元素的地址。
五,指针与堆空间
各类内存空间不同,用途不同:
——全局数据区:存放全局变量,静态变量;
——栈空间:存放函数参数,局部变量;
——堆空间:用于动态创建变量
堆空间的本质:
-
备用的“内存仓库”,以字节为单位预留可用内存。
-
程序可在需要时申请借内存。(动态借)
-
借完后需要及时归还。(动态还)
问:如何从对卡申请借内存,如何归还呢?
预备知识——void*
-
void类型时基础类型,对应指针类型为void*
-
void*为指针类型,其指针变量能够保存地址
-
通过void*指针无法获取内存中的数据(无长度信息)
-
void*保存的内存有起始地址,但没有长度信息。能够保存任意类型的地址,能转换到其它指针类型的变量。
-
不可以用void*指针直接获取内存数据,不过void*与其它数据指针可以相互赋值。
堆空间的使用原则:
-
有借有还。
-
malloc申请内存后,应该判断是否申请成功。
=NULL,则申请不成功。 !=NULL,则申请成功。 -
free负责释放申请到的内存。