C语言:指针
===
指针概念
---
指针变量也是一个变量
指针存放的内容是一个地址,该地址指向一块内存空间
指针是一种数据类型
指针变量定义
---
内存最小单位:BYTE字节(比特)
对于内存,每个BYTE都有一个唯一不同的编号,这个编号就是内存的地址
一个地址编号对应的是一个BYTE的空间大小
一个地址编号在32位系统下,是一个4个字节的无符号整数;在64位系统下是一个8个字节的无符号整数
[代码:指针的定义](def_pointer.cpp)
```
int *p;
//p:指针变量,存放地址
//*p:指针所指内存的实际数据
*p = 10//p指向的地址存放的值是10
//指针变量只能存放地址,不能将一个int型变量直接赋值给一个指针
```
取地址符号&(found/address)
---
&可以获取一个变量在内存中的地址
register int a;//register限定符,a变成寄存器变量,存放在cpu里而不是内存中,所以是没有地址的,不能用&进行取地址操作
void指针
---
void代表无类型,可以指向任何类型的地址
[代码](def_pointer2.cpp)
指针占用内存
---
在同一个系统下,不管指向什么类型的变量,地址编号的大小总是一样的(32位系统占4个BYTE,64位系统占8个BYTE),但是不同类型变量占用的内存是不同的,见下方的代码
就像在一个酒店里,不管是单人间,双人间还是标准间,门牌号的大小都是一样的(4位数/8位数)
[代码:指针占用内存说明](RAM_pointer.cpp)
上述的代码与下面的代码进行比较
[代码:不同类型变量占用的内存大小](pointer_address.cpp)
空指针与野指针
---
空指针:如果一个指针变量没有明确得指向一块内存,那么就把这个指针变量指向NULL,空指针是合法的
野指针:没有初始化过值的指针(没有指定内存),野指针是非法的
程序中避免野指针,可以使用空指针
[代码:空指针与野指针](NULL_pointer.cpp)
指针的兼容性
---
指针类型之间一定要匹配,指针之间的赋值比普通数据类型之间的赋值要更严格
```
int a;
double b = 3.45;
a = b;//正确,a = 3
int *p = &b;//错误,类型不一致
```
大白话:不要把指针想的太神秘,指针变量只是个变量而已,它里面放的就是一些地址编号,这些地址编号就是无符号的整数,在32位系统下是4个字节,在64位系统下是8个字节,但是这些整数不能直接赋值,来源于另外一个变量的取地址操作
指向常量的指针与指针常量
---
#### 指向常量的指针
```
int a = 1;
const int *p = &a;//p可以指向一个int类型的地址,但不可以用*p的方式修改这个内存的值
*p = 10;//会报错:不能给常量赋值
printf("a = %d\n",a);
```
对于常量来说,值不能改变
```
const int b = 0;
b = 10;//报错,b为常量,值不能改变
```
但是可以创建一个指针指向它,修改
```
const int b = 0;
int *p = &b;
*p = 0;//不会报错,但是会warning,实际上这是不合理的,c语言的漏洞
```
c语言中的const是有问题的,可以通过指针变量间接修改const常量的值(c++中是无法修改的),所以在c语言中用#define常量的时候更多
#### 指针常量
```
int *const p2 = &a;//p2只能指向a的地址
p2 = &b;//错误,p2是一个常量指针,只能指向固定的一个变量a的地址
//但是可以通过*p2来读写这个变量的值
*p2 = 10;
```
注意区分常量指针与指针常量
指针与数组的关系
---
```
p=a;数组的名字就代表数组第一个元素的地址,等同于 p = &a[0]
```
```
p1 = &a[5];//把a5的地址给指针p1
*p1 = 1000;//改变a[5]的值
p1[2] = 666;//p1指向a[5],则p1[2]顺延指向a[7],改变的是a[7]的值,把数组想象成一个队列
```
```
p[3] = 100;//当指针变量指向一个数组的时候,c语言语法规定指针变量名可以当数组名用,区别在哪里?
//区别:
printf("%lu,%lu\n", sizeof(a),sizeof(p));//对数组来讲返回数组的大小40,对指针来讲返回指针的大小4
```
[完整代码](poin_array.cpp)
指针运算
---
指针变量可以计算,int* 类型加一,变化4个整数(增加4个字节),char* 类型加一,变化1个整数
[代码1](poin_add1.cpp)
[代码2](poin_add2.cpp)
增加/减少指针值:p++;p--
求差值:pa-pb,通常用于同一个数组内求两个元素之间的距离
比较:pa == pb,通常用来比较两个指针是否指向同一个位置
通过指针使用数组元素
---
[代码](poin_ary.cpp)
c语言中所有数据类型都可以理解为一个char的数组
练习:把ip地址转化为整数
---
输入ip地址
char a[100]="192.168.2.5"
把这个ip转化为unsigned int类型的整数
[代码](ip_int.cpp)
练习:利用指针进行多维数组排序
---
[指针多维数组排序](poin_2array.cpp)
指针数组
---
指针数组的定义:
```
char *a[10];//定义指针数组a,每个成员是char*类型的,一共10个成员
int *b[10];//定义指针数组b,每个成员是int*类型的,一共10个成员
printf("%lu,%lu\n",sizeof(a),sizeof(b));//结果:40,40
```
给数组成员赋值:
```
char i = 0;
//a = &i;//a和b为数组名,数组名不能作为左值
//b = &i;
a[0] = &i;//合法
printf("%lu,%lu\n",sizeof(a[0]),sizeof(*a[0]));//输出结果4,1
```
[完整代码](pointer_array.cpp)
二级指针——指向指针的指针
---
```
int a = 0; 地址是0x123456
int *p = &a; p为0x123456,*p为0,指针p的存放地址是0x100
int **pp = &p; pp为0x100(p的地址), *pp为0x123456,**pp为0
```
[代码](pointer2.cpp)
对于一个指针变量b,想指向它需要定义一个二级指针a
多级指针
---
能用低级指针的尽量不要用高级指针,一级指针二级指针最常用,三级指针很少
[多级指针](pointer3.cpp)
```
int a = 0;
int *p = &a;
int **pp = &p;//pp代表p的地址,*pp代表a的地址,**pp代表a的值
int ***ppp = &pp;//ppp代表pp的地址,*ppp代表p的地址,**ppp代表a的地址,***ppp代表a的值
```
函数的参数作为指针变量
---
c语言想通过函数内部修改实参的值,只能给函数实参传递实参的地址来间接修改实参的值
[代码](poin_function.cpp)
思考代码为什么输出为4和40?[代码](array_poin.cpp)
```
以下三条语句是一样的:
void test(int a[10])//当数组名作为函数形参时,c语言将数组名解析为指针
void test(int *a)//最常用最简单
void test(int a[])
```
函数指针参数使用const保护:
```
void test(const int *a)//为了不让函数内部修改数组成员的值
```
在c语言中,可以转个弯(强转)在函数内部修改成员的值(限制菜鸟),但是在c++中是改不了的
函数的返回类型可以是指针类型
---
```
int *test()
{
return NULL;
}
```
memset与memcpy与memmove
---
memset:将指定区域的内存置空(参数1:指定要置空内存的首地址;参数2:0;参数3:这块内存的大小,单位,字节)
```
memset(a,0,sizeof(a));
```
[memset](memset_.cpp)
memcpy:在两块内存之间拷贝数据(参数1:目标地址;参数2:原地址;参数3:拷贝多少内容,字节)
```
memcpy(a,b,sizeof(b));
```
[memcpy](memcpy_.cpp)
memmove:移动内存(参数与memcpy一致)
```
memmove(a,b,sizeof(b));
```
注意:使用memcpy的时候一定要确保内存没有重叠区域
```
memcpy(&a[3],&a[0],20);//出现内存重叠区域
```
指针小结
---
```
int i; 定义整型变量
int *p; 定义指向int型变量的指针变量
int a[10]; 定义int数组
int *a[10]; 定义指针数组,数组中的每个元素指向一个int型变量的地址
int func(); 定义函数,返回值类型为int
int *func();定义函数,返回值类型�
c语言学习内容:指针.zip
需积分: 2 17 浏览量
2023-10-24
18:52:41
上传
评论
收藏 16KB ZIP 举报
z同学的编程之路
- 粉丝: 2509
- 资源: 2135
最新资源
- (大赛作品)STM32实现的F072RB NUCLEO智能家居控制.zip
- STM32实现的数字示波器源码+数字信号处理教程、配套实例.zip
- 【cookie续续】【cookie续续】【cookie续续】
- 低功耗STM32实现的F411开发板(原理图+PCB源文件+官方例程+驱动等).zip
- 基于stm32实现的 nucleo-L476的智能灯(操作说明+源码).zip
- 基于STM32实现的 NUCLEO板设计彩色LED照明灯(纯cubeMX开发).zip
- 基于STM32实现的 的联合调试侦听设备解决方案(原理图、PCB源文件、调试工具、视频).zip
- 基于STM32实现的 人群定位、调速智能风扇设计(程序、设计报告、视频演示).zip
- 哔哩下载姬(DownKyi)
- 千纬认字app再次更新,增加部首、笔画动画功能
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈