当前位置:网站首页>【指针初解】
【指针初解】
2022-08-03 16:53:00 【悄悄卷s所有人】
这里写目录标题
一、指针是什么?
1.指针是内存中一个最小单元(字节)的编导,也就是地址。
2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
3.int a=0;int* p=&a;
在 int* p 中,int 是指p所指向的 a 的类型是int 型;int*是p的类型。
(一)、指针变量
我们可以通过取地址操作符(&)取出变量的内存起始地址,把地址存放到一个变量中,这个变量就是指针变量。
总结:
指针变量是用来存放地址的变量,(存放在指针中的值都被当成地址处理)。
大小:
在32位的机器上,一个指针变量的大小是4个字节。
在64位的机器上,如果有64个地址线,那一个指针变量的大小是8个字节。
二、指针和指针类型
1.指针类型决定了:指针进行解引用操作的时候,访问几个字节(权限)。
如:
char* 的指针解引用访问1个字节
int* 的指针解引用访问4个字节
double* 的指针解引用访问8个字节
…
2.指针类型决定了指针的步长(向前/向后 走一步是多大的距离)
int* 指针+1,意思是跳过一个整形,也就是向后走4个字节
char* 指针+1,意思是跳过一个整形,也就是向后走1个字节
double* 指针+1,意思是跳过一个整形,也就是向后走8个字节
…
三、野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。
(一)、成因:
1.指针未初始化
#include<stdio.h>
int main()
{
int* p;//局部变量指针未初始化,默认值为随机值
*p = 20;
return 0;
}
2.指针越界访问
#include<stdio.h>
int main()
{
int arr[10] = {
0 };
int* p = arr;
int i = 0;
for (i = 0; i <= 10; i++)//当指针指向的范围超出数组arr范围时,p就是野指针
{
*(p++) = i;
}
return 0;
}
3.指针指向的空间释放
#include<stdio.h>
int* test()
{
int num = 100;
return #
}
int main()
{
int* p = test();
*p = 200;
printf("%d", *p);
return 0;
}
当主函数中用一个整形指针变量p来接收test函数的返回值时,p中存放的是num的地址,但num的地址在出函数时已经释放还给了操作系统,所以当给*p赋值200时,原来num的地址已经不属于函数,这时给其赋值将可能会覆盖掉正在使用这个地址空间的系统内容,虽然程序能够执行,但存在安全隐患。
(二)、如何规避野指针
1.指针初始化
2.小心指针越界
3.指针指向空间释放,及时置NULL(空指针,相当于将int中的变量初始化为0)
4.避免返回局部变量 的地址(即避免返回 栈空间的地址)
5.指针使用之前检查有效性
四、指针运算
1.指针 +(加) 、-(减) 整数
加法与减法运算规律一致。
如:
int* p=NULL;
p+1; //表示跳过一个整形的长度
*p++ == *(p++);
即*p++;等同于:*p; p += 1;
解析:由于* 和++的运算优先级一样,且是右结合。
故* p++相当于* (p++),p先与++结合,然后p++整体再与* 结合。
前面陈述是一种最常见的错误,很多初学者也是这么理解的。
但是,因为++后置的时候,本身含义就是先运算后增加1
(运算指的是p++作为一个整体与前面的* 进行运算;增加1指的是p + 1),
所以实际上 * p++符号整体对外表现的值是 * p的值,运算完成后p再加1。
【注意】是运算后p再加1,而不是p所指向的变量*p再加1
————
2.指针 - (减)指针
**注意:
1.没有指针 + 指针 这种运算!!
2.指针相减的前提是:指针指向的是同一块连续的空间
3.两个指针要是同类型的才能相减,否则程序可能会出错(不知道以哪个类型来进行计算)。
**
如图显示代码:用&arr[9]-arr[0]所得到的是它们之间元素的个数。即:指针与指针相减的绝对值是它们之间元素的个数。
3.指针的关系运算
包括 < > 运算
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面那个指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
五、指针和数组
1.数组和指针不是一个东西,数组能够存放一组数,空间连续,大小取决与数组中元素的类型和个数;指针是一个变量,是存放地址的,大小为4个或8个字节。
2.它们之间的联系:
数组名(即arr)是地址(指针)(&和sizeof两种情况除外),数组把首元素的地址,交给一个指针变量后,可以通过指针来访问数组。
六、二级指针
注:三、四级指针与二级指针相类似,但使用较少。
概念:
将一个指针的地址放到另外一个指针里,那么,另外的那一个指针就是二级指针。
#include<stdio.h>
int main()
{
int a = 10;
int* p = &a;//p就是一级指针变量
int** pp = &p;//pp就是二级指针
printf("%d\n", a);
*p = 20;
printf("%d\n", a);
**pp = 30;//**pp=*(*pp)=*p=a
printf("%d\n", a);
return 0;
}
上述代码中,int** pp 中的int* 表示的是指pp所指向的 p的类型是int* 型,是一个指针变量,p 中存放的是a的地址;int** 是pp的类型。第二个 * 是指 pp是一个指针。
七、指针数组
指针数组:即存放指针的数组;如:整形数组int arr[ ]是存放整型的数组。字符数组char arr[ ]是存放字符的数组。
int* arr[ ] 存放整型指针的数组
char* arr[ ] 存放字符型指针的数组
duoble* arr[ ] 存放双精度浮点型指针的数组
…
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int* arr[5] = {
&a,&b,&c,&d,&e };
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", *(arr[i]));//逐个打印出arr中的每一个元素
}
return 0;
}
总结
以上内容是我的一些经验总结,如有疏漏敬请指正。
如果觉得内容对您有所帮助,请一键三连噢!!谢谢。
边栏推荐
猜你喜欢
C专家编程 第1章 C:穿越时空的迷雾 1.9 阅读ANSI C标准,寻找乐趣和裨益
正向代理与反向代理
deepstresam的插件配置说明,通过配置osd,设置字体的背景为透明
蒋松廷 荣获第六季完美童模全球总决赛 全球总冠军
Web3 安全风险令人生畏?应该如何应对?
phoenix创建映射表和创建索引、删除索引
附录A 程序员工作面试的秘密
“LaMDA 存在种族歧视,谷歌的 AI 伦理不过是‘遮羞布’!”
Interviews are no longer hanged!This is the correct way to open the seven schemes of Redis distributed locks
面试突击71:GET 和 POST 有什么区别?
随机推荐
Cookie和Session的关系
如何直击固定资产管理的难题?
【目标检测】Focal Loss for Dense Object Detection
LeetCode·72.编辑距离·动态规划
Big guys.Use flink-cdc-sqlserver version 2.2.0 to read sqlserver2008R
沃尔沃:这是会“种草”的“安全感”!
yolov5s用自己的数据集进行训练模型
How ArkUI adapter somehow the screen
C语言02、语句、函数
Description of the functional scenario of "collective storage and general governance" in the data center
高效的组织信息共享知识库是一种宝贵的资源
node连接mongoose数据库流程
通俗理解apt-get 和pip的区别是什么
JS 字符串转 GBK 编码超精简实现
面试不再被吊打!这才是Redis分布式锁的七种方案的正确打开方式
uniapp 去掉默认导航栏
C语言01、数据类型、变量常量、字符串、转义字符、注释
Excuse me this hologres dimension table is cached?How to Finished
Adobe是什么?
并发高的情况下,试试用ThreadLocalRandom来生成随机数