指针:一种特殊的变量
指针是C语言中的变量
- 可以用于保存具体值
- 特殊之处,指针保存的值是内存中的地址
内存地址是什么?
- 内存是计算机中的存储部件,每个存储单元有固定唯一编号
- 内存中存储单元的编码即内存地址
地址获取
- C语言通过&操作符获取程序元素地址
- &可以获取变量,数组,函数的起始地址
- 内存地址的本质是一个无符号整数(4字节[32位],8字节[64位])
#include <stdio.h>
int main()
{
int var = 0;
printf("var = %d\n",var);
printf("&var = %p\n",&var);
return 0;
}
指针语法 type* pointer
指针内存访问: *pointer
- 指针访问操作符(*)作用于指针变量即可访问内存数据
- 指针类型决定了通过地址访问内存时的长度范围
- 指针的类型统一占用4字节或8字节
初学指针的规则
- Type* 类型的指针只保存Type类型变量的地址
- 禁止不同类型的指针相互赋值
- 禁止将普通数值当作地址赋值给指针
指针于数组
- 使用取地址操作符&获取数组地址
- 数组名可看作一个指针,代表数组中0元素的地址
- 当指针指向数组元素时,可进行指针运算
对于指针与数组中
int a[] = {5,48,45,4}; int *p = a; int i = 0;
有如下关系
a[i] == *(a+i) == *(p+i)
字符串
C语言中字符串常量的类型是什么?
答: char * 类型,一种指针类型。
指针移动组合
int v = *p++
解读
- 指针访问符(*)和自增运算操作符(++) 优先级相同
- 先从p指向的内存中取值,然后p进行移动
指针与函数
深入函数
- 函数的本质就是一段内存中的代码(占用一片连续的内存)
- 函数拥有类型,函数的类型由返回类型和参数类型列表组成
//函数类型
//函数声明 类型
int sun(int n) int(int)
void swap(int *a,int *b) void(int*,int*)
注意
- 函数名就是函数体的起始地址(函数入口地址)
- 通过函数名调用函数,本质位指定具体地址的跳转执行
- 可以定义指针保留函数入口地址
函数指针(Type func(Type1 a,Type2 b))
- 函数名即函数入口地址,类型Type(*)(Type1,Type2)
- 对于func的函数,&func与func数值相同,意义相同
- 指向函数指针:Type (*pEunc)(Type1,Type2) = func
函数指针参数
- 函数指针的本质还是指针(变量,保存内存地址)
- 可定义函数指针参数,使用相同代码实现不同功能
#include <stdio.h>
int add(int a,int b)
{
return a+b;
}
int calculate(int a[],int len,int(*cal)(int,int))
{
int number=a[0];
int i=0;
for(i=1;i<len;i++)
{
number=cal(number,a[i]);
}
return number;
}
int main(int argc, char const *argv[])
{
int a[] = {1,2,3,4,5,6,7,8,9};
printf("1+2+....+9=%d\n",calculate(a,9,add));
return 0;
}
注意
- 函数指针只是单纯的保存函数入口地址
- 因此
- 只能通过函数指针调用目标函数
- 不能进行指针移动(指针运算)
指针与堆空间
内存区域不同,用途不同
- 全局数据区:存放全局变量,静态变量
- 栈空间:存放函数参数,局部变量
- 堆空间:用于动态创建变量(数组)
堆空间的本质
- 备用的“内存仓库”,以字节为单位预留的可用内存
- 程序可在需要时从“仓库”中申请使用内存(动态借)
- 当不需要在使用申请的内存时,需要及时归还(动态还)
如何在堆空间申请内存?如何归还?
预备知识 – void*
- void类型是基础类型,对应的指针类型为 void*
- void*是指针类型,其指针变量能够保存地址
- 通过void*指针无法获取内存中的数据(无长度信息)
void*总结
- 不可使用void*指针直接获取内存数据
- void*指针可与其他数据指针相互赋值
堆空间的使用
- 工具文件:stdlib.h
- 申请:void* malloc(unsigned bytes)
- 归还:void free(void* p)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
int *p = malloc(2*sizeof(int));
if (p != NULL)
{
*p = 1;
*(p+1) = 2;
for (size_t i = 0; i < 2; i++)
{
printf("%d ",p[i]);
}
free(p);
}
return 0;
}
堆空间使用原则
- 有借有还
- malloc申请内存后,应该判断是否申请成功
- free只能释放申请到的内存,且不可以多次释放