概述
目录
1.指针是什么
2.地址与指针
3.指针的表达式
4..指针与 *
5.指针类型的意义
6.指针的意义
7.我们常说的野指针是什么?该怎么避免?
8.指针的操作
9.指针与数组
10.const与指针
1.指针是什么?
通俗来讲指针可以直接理解成地址。内存中存储着数据,那用户要访问这些数据总要知道去哪里访问吧,这就引申出地址的概念,好比我们国家的街道有名称 有编号,然后根据这些就可以找到对面存放的数据,那么名称,编号在计算机中便是地址,我们可以通过地址找到对应的数据内容,这就有种指向的感觉,因此地址也被称为指针。
2.地址与指针
既然说到地址,那就不得不说&(取地址符),&获得变量的地址(必须是变量),取出的地址的大小取决于编译器是32位编译还是64位编译。
什么是32位编译,即指有32根地址线,他们负责高频通电代表1,低频通电代表0,这样就会有32个代表二进制的数,一个代表一个位(比特),8个比特代表一个字节,因此32个比特最大可以表示4字节的数,因此有时我们打印地址时写成%d可能更结果没啥区别就是因为int也是4字节,但如果是64位就不对了
打印地址一般用%p,或者可以用%x打印16进制数
ps:地址自顶向下连续分配
3.
int* p = &a;
int *p,*q;// int *p,q;
现在看这个表达式,这里表述的意思是p是一个指针,他指向的变量的类型是int,他指向a的地址
第二个是连续定义指针(这里没初始化,就是没让指针指向一个确定的地址)【这种行为非常危险!】
初学者容易写成//右边的内容,但其实这样只定义了一个指针一个int类型的变量.
这里需要注意,p是变量(指针变量),不是*p,只能说可以把*p当成一个整体,是int类型
*p是一个表达式运算的结果,是一个特殊的值,再次强调他不是变量,p才是变量。
4.指针与 *
*是一个单目运算符,用于访问指针所指的地址代表的变量 ps可以靠近int(类型),也可以靠近p(变量)
5.指针类型的意义
前面提到指针的大小只与编译器的位数有关,那么在同一个工程中,char*更int*大小是一样的,那么为什么需要指针类型?
1.指针类型决定了再解引用(*)的时候一次访问几个字节,int*是4个字节,char*是一个,我们前面提到32位是4字节,这代表一个数据占用4字节,假设为10 那么就是00 00 00 0a(16进制,a代表10,拆开就是32个二进制){下面内存存放是倒着的}
【指针的权限】
如果用char*类型,*pa只能访问一个字节即0a,但是int*可以访问00 00 00 0a
2.还涉及到指针的加减整数 (在数组中)
在c primer plus 上面提到“指针加整数,整数先和指针所指的类型的大小(字节单位)相乘,然后把结果和地址相加”,
即如果p指针指向a[0],p+4就等于a[4]
这又引申出一个问题:如果加完超出数组怎么办?
c语言规定了指针允许指向数组末尾元素的后一个元素,即a[10]是0到9下标,那么a[9]后面那个地址c是允许指针有效的,但是不保证里面的数值(即你可以指,但不能访问)【方便代码简洁】
ps:c没规定可以指首元素的前一个元素哦!
6.指针的意义
为什么要用指针,可能很多初学者会有这个问题,我一开始也是 ,明明靠着数组,循环,函数就能解决很多问题
1.函数需要返回多个值,我们知道return只能返回一个值,那怎么返回多个呢?
这时可以用过指针,解引用操作改变地址中的数据,返回的时候自然能带回改变的数值
2.传递较大变量时,函数的使用是在内存的栈区中的,每次调用函数都会有个压栈操作,即把函数的代码压入栈中,当你一次调用一个很大的数据,栈区可放不下,因此这是可以用过指针指向数组的第一个元素传入函数(数组在内存空间的地址是连续的),传递数组名就是传递首元素的地址,也就是传递指针,某种程度上指针与数组不分家。
3.特殊场景,如函数需要返回状态值,即if(函数返回1,-1,0)这些来判断是否执行,但是我们想在函数执行的同时保留变量的变化,这时可以通过指针来操作变量
等等,指针远远不止上面的操作,还有很多其他用途
指针是c语言为什么能称为最接近底层的语言的原因,当你熟练掌握指针,你可以随心所欲对内存想怎么操作怎么操作。
7.我们常说的野指针是什么?该怎么避免?
野指针就是指针指向的变量未知,这种情况非常危险。加入你不知道并且用*操作他可能就会导致一些奇怪的bug
成因大概分为三种:
1.指针未初始化 int* p; *p=20;
直接对未初始化的指针进行取值操作可能会导致程序崩溃
2.指针越界访问
3.指针指向的空间释放
那么应该怎么避免?
1.初学者一定要记得初始化(你知道指向那个变量就初始化那个变量,不知道就给NULL)记得大写!
2.不用的指针可以及时赋为空指针
8.指针的操作
赋值,解引用,比较,指针与整数相加,两个指针相减
就说一下两个指针相减,前面的前文都有提到
指针相减要求是在同一个数组中,相减可以得到他们的距离(即他们之间有几个元素)
ps:指针相加没有意义,因此指针间没有相加的运算
9.指针与数组
1.数组变量其实是特殊的指针(数组变量本身代表地址)
ps但数组单元表达的是变量需要&
arr=arr[0],arr[0]是arr的一个数组单元
2.在数组中指针+1就是从指针指向的位置跳过一个单元(元素)
3.[]也可以用于指针,
int min=10;
int *p=&min;
printf("%d",p[0]);//等价与printf("%d",*p);
理解:p把min当成一个长度为1的数组,p[0]是第一个元素,因此等价
ps p[]可以有负数,就是向左移
10.const与指针
简单的提一下,分为两种
1.int*const a
const代表a是一个常数,也就是说一旦这个指针初始化了就不能改变指向了
可以改变指向的变量的值,不可以改变指向的变量,也就是说指向变量a就不能比变了,但是我可以改变a的值
其实数组变量也是上面的类型,为什么说数组与数组之间不可以直接赋值,就是因为int a[ ]等价于int* const a,也就是a本质上是指针,并且不能改变指向
const代表a是常数,初始化出来了就不能被改变,也就是不能代表别的数组
2.const int*a
可以改变指向,但是不能改变指向的变量的值
可以理解成 const + int*a。int*a可以随便指,但是指完之后被const修饰就变成常量(即不能改变)
3.双const修饰
const int* const a ,啥都不能改变,不能改指向,也不能改值
有什么意义呢?
一般用于保护数据,因为c允许指针访问内存,一旦你做的项目里出现了野指针,并且刚好指向你程序的数据,当你修改的时候也就变相修改了你的内存,这种错误很隐蔽,也很难发现,也很致命。
因此可以用const修饰来达到你针对指向和值的限定
最后
以上就是简单毛巾为你收集整理的C语言 初识指针2.地址与指针的全部内容,希望文章能够帮你解决C语言 初识指针2.地址与指针所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复