admin管理员组文章数量:1794759
【c语言学习】深入理解指针(1)
前言
相信大家在学习c语言的过程中都被指针所折磨过吧,的确,指针作为c语言学习的一大难点,确实比较难以理解,我在学习的过程中也是跟不上学校老师的思路,哇,这是什么,这地址那地址的,取地址又解引用的,真烦,后来经过一段时间的学习,对指针的理解也更加清晰,之前的疑惑也都解开了,那么本篇文章就我自己的理解给大家介绍一下指针。
内存和地址
讲到指针肯定离不开内存和地址,其实指针就是地址,可以把内存和地址分别理解为一个学校的宿舍,宿舍就是内存,给每一个宿舍标上门牌号,作为地址方便查找,也就是指针。
0XFFFFFFFF也就相当于门牌号,这些地址都被存放在内存单元中,一个内存单元也就是一个字节
取地址操作符(&)和解引用操作符(*)
&就是把内存中的地址拿出来
因为 int 类型占四个字节,我们通过&得到的为四个字节里的较小地址的编号,那么我们把地址取出来干什么呢,肯定是拿来用的,所以我们得先把地址存起来,那么用来存放地址的变量就称为指针变量
代码语言:javascript代码运行次数:0运行复制#include <stdio.h>
int main(){
int a = 10;
int* p = &a;
*p = 0;
printf("%d\n",a);
return 0;
}
p 就作为了指针变量来存储a的地址,类型为int* ,那么我们又怎么去使用地址呢,就需要用到解引用操作符 * ,代码中 *p就是通过指针变量p里面存放的地址找到指定的空间进行修改。 总结来说呢,取地址& 和 解引用 就是一对相反的操作,&把地址拿出来,解引用 就是顺着地址再找回去。
指针变量
在上面已经提到,指针变量就是用来存放指针的变量,那么既然是变量,大小又是多少呢。 在32位计算机下指针变量的大小为4个字节,64位时指针变量的大小为8个字节。
可以看出,无论前面定义的类型是什么,在X86环境下,指针变量的大小就是4个字节,X64环境下,指针变量的大小就是8个字节。 那么前面定义的类型又有什么意义呢
首先,pa和pc里面都存的是a的地址,所以输出结果相同,又由于指针变量类型不用,后面进行指针运算的时候,同时加一,但增加的字节不同,可以看出,char*类型的加了一个字节,int *类型的加了4个字节。
void*类型指针
在前面我们看到了int *,char *等一些指针类型,还有一种类型比较特殊
代码语言:javascript代码运行次数:0运行复制#incldue <stdio.h>
int main(){
int a = 0;
float b = 0.0;
void* p1 = &f;
p1 = &a;
}
void* 类型的指针可以存放其他类型的指针,但也因为这个原因,它不能像其他指针那样进行+1 , - 1等一些操作,因为不知道每次加减多少字节。
const 修饰指针变量
const 修饰指针变量时,可以放在*左边也可以放在右边,但所产生的效果是不相同的。
下面我们通过具体的例子来感受一下:
当我们把const 放在* 右边时,指针变量p就不能再指向其他地址了,编译器就会报错
但是我们却可以通过解引用,来修改值,我们再看下面一组例子:
当我们把const放在*的左边时,产生的效果就和上面的情况相反了。
总结: 当const放在右边时,限制的是指针本身(不能改变指针变量指向),可以改变指针指向内容。 当const放在左边时,限制的是指针指向的内容,不能修改,但是可以修改指针变量本身(改变指针变量指向) 其实也好理解,*p表示指向的内容,p就是指针本身const * p限制内容, *const限制指针本身。
指针运算
指针±整数
我i们直接说结论
int a = 0; int * p = &a; p+1; 这里的p+1就是在指针p原来表示的地址基础上又加了4个字节,那为什么是4个字节呢,其实是个前面的int 有关的 type * p; p+n跳过n*sizeof(type)个字节
那么这个有什么用呢,我们可以联想一下数组
我们可以用指针加减整数的方式访问数组元素,操作如下:
代码语言:javascript代码运行次数:0运行复制int main() {
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(a) / sizeof(a[0]);
int* p = &a[0];//首元素地址
for (int i = 0; i < sz; i++) {
printf("%d ", *p);
p++;//每次加四个字节,正好访问下一个元素
}
return 0;
}
指针 - 指针
我们可以把指针加减数字理解为日期加减天数,得到的就是加减后的日期,那么指针减指针就是日期减日期,就是两个日期之间相差的天数,但是指针加指针是没有意义的。
不过指针相减前提是两个指针指向的是同一块区域,不然相减是没有意义的
指针比较大小
既然指针可以相减,那么指针肯定是有大小的,数组中随着下标的增长就是从低地址到高地址,根据这个我们来看个样例
代码语言:javascript代码运行次数:0运行复制int main() {
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(a) / sizeof(a[0]);
int* p = a;//数组名就是数组首元素地址
while (p < a + sz) {
printf("%d ", *p);
p++;
}
return 0;
}
根据上面的代码同样可以实现数组的遍历。
野指针
野指针就是指针指向的位置是不可知的,随机的
同时呢,越界访问也会产生野指针,因为数组中内存连续,但出了数组,内存分配又是随机的
代码语言:javascript代码运行次数:0运行复制还是上面的代码,这次我们改为 i<=sz
int main() {
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(a) / sizeof(a[0]);
int* p = &a[0];//首元素地址
for (int i = 0; i <= sz; i++) {
printf("%d ", *p);
p++;//会越界访问,变成野指针
}
return 0;
}
那么如何规避野指针呢 规范的进行初始化,如果不知道指针指向哪里,可以先给指针赋值NULL,使用的时候检查指针的有效性。 本次分享就先到这里了,感谢支持!
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-03-10,如有侵权请联系 cloudcommunity@tencent 删除内存数组指针int变量本文标签: c语言学习深入理解指针(1)
版权声明:本文标题:【c语言学习】深入理解指针(1) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1754848007a1707274.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论