栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

==指针初阶==

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

==指针初阶==

1、指针的定义

将内存空间划分为一个个内存单元,1个内存单元占1byte,将内存单元的编号称为地址(地址也叫作指针)。
指针也就是内存单元的编号
口语中常说的指针指的是指针变量

int main()
{
	int a = 10;//a是一个整型变量,占用4个字节的内存空间
	int* p = &a;
	//p 是一个指针变量 &a取出的是0x00dbfd98
	return 0;
}


每个内存单元的地址都是硬件生成的,不需要单独存储。除非进行取地址操作将其存放在指针变量中,内存单元的地址才会存储。

总结
指针就是地址,口语中的指针就是指针变量
指针变量中存放的就是地址,通过地址就可以找到一个内存单元

2、指针变量

采用1比特位太小,1kb太大,所以采用1个字节对应一个地址

对于64根地址线
2^64/1024/1024/1024=17,179,869,184
可以看出64根地址的编址空间非常大
总结
指针变量是用来存放地址,而地址是用于唯一标识一块地址空间(内存单元)
指针的大小在32位平台上是4个字节,而在64位平台上是8个字节。

X86 指的是32位平台
X64 指的是64位平台

3、指针和指针类型


sizeof返回的是无符号整型 unsigned int(使用%d可能会发生报错,严格意义上来说用%u或者%zu)
输出:32位平台4个字节 64位平台8个字节

小补充:16进制位
0x11223344
两个16进制位表示1个字节大小

调试监视窗口 内存窗口
调试按F10进入调试
F11往后走
不能通过移动箭头来实现(移动箭头只是移过去了,中间过程都跳过了)

既然char 、int、double指针变量的大小都是4/8个字节为啥还要区分指针类型,直接创建一个专属指针变量的类型不好吗?

将int 类型的地址赋值给char* 只是报警告

char* pc 是存放的是a的地址的(因为都是指针变量,在同一位平台下指针大小是相同的),但是在解引用的过程中char * pc只能解引用1个字节空间,所以指针类型是有意义的。

指针类型作用1:


pa(int型指针)+1跳过4个字节
pc(char型指针)+1跳过1个字节

指针类型作用2:

总结
指针类型存在的意义:
方便访问内存空间,你要是想1个字节1个字节访问就用char* 一个整型一个整型访问就用int*


int* 和float* 指针访问空间大小虽然一样,但是不能混用
int类型指针认为里面存放的是int类型的变量,float类型指针认为里面存放的是float类型的变量,所以在内存中存储的数据是完全不同的

浮点数和整型在内存中存储方式 ,完全不同没有可比性

地址类似于门牌号用来唯一标识某一内存空间,门牌号后面的房间大小取决于指针变量的指针类型。

4、野指针

野指针的概念:指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

野指针的成因 1)指针未初始化


这里p没有初始化,就意味着没有明确的指向
一个局部变量不初始化,放的是随机值:0xcccccccc
0xcccccccc所指向的地址是不属于我们的,*p =10 给非法地址赋值
非法访问内存空间

2)指针越界访问


arr表示首元素地址,p指针指向首元素地址
for循环进行了11次而arr数组空间只有十个,所以最后一次循环造成越界。
当指针指向的范围超出arr的数组范围,p就是野指针。

3)指针指向的空间释放


p指针指向test函数 test函数中将a赋值10,返回a的地址(0x0012ff40)
test函数中a是局部变量,出了函数空间就会被释放,也就是将内存空间归还给操作系统
但是p指针还记得a的地址,a已经被销毁了。p指针访问的空间是非法的
销毁:test函数向内存空间申请了四个字节的空间,在函数调用结束后归还给操作系统,就是说没有访问这块空间的能力,而不是说少了一块内存空间。

避免出现野指针的方法


当我们不知道将指针变量赋什么值时,将它赋为NULL等价与将变量赋值为0
(int *p2 =NULL —> int b = 0)
如果指针变量为NULL,无法对其操作

NULL是内存中的0地址,计算机是无法访问内存中NULL地址。

这里虽然加了判断条件,但是p本身就不是空值
p是野指针是可以指向test函数的内存空间的,这份内存空间还在只是不属于我了,如果该空间未被别人使用,仍旧可以打印出10
但是我们在前面加上几个print打印的就不是10(空间被使用了)

test函数调用完成后,函数栈帧的空间就空出来了,而后面的print又调用了函数栈帧,a的空间就被覆盖了
返回的就是随机值

5、指针运算 5.1 指针加减整数


先 * vp =0 再 vp++

指针加减整数的用法

5.2 指针-指针


arr[9]和arr[0]之间有9个元素
但是&arr[0] - &arr[9] = -9
所以应该说指针-指针的绝对值得到的是指针之间的元素个数


这是两个不同的空间,相减都不知道表示是int的个数还是char的个数,所以是err
指针-指针的用法(计算字符串长度strlen)

5.3 指针的关系运算


先 --vp 再 * ( )=0

简化代码,这样看上去更直观



C语言标准规定p1允许与p2进行比较,但不允许与p3比较
一般是正向遍历就会与p2进行比较,逆向遍历则与p3比较

6、指针与数组


&arr[ i ] 和 p + i 是等价的 两个方式打印出来的地址是一样的

arr[ i ] 在计算机使用时会转换成 *(arr + i)
上面三种printf打印结果是一样的

7、二级指针


二级指针变量是用来存放一级指针变量的地址

8、指针数组



用指针数组来实现二维数组

这两个是完全等价的

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001890.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号