当前位置:   article > 正文

C语言高级-指针_在c语言中如何让指针精准的指向一个内存地址

在c语言中如何让指针精准的指向一个内存地址

第一点:

使用指针三步骤:定义指针变量、给指针变量赋值(绑定指针)、解引用

第一步:定义指针变量

int *p //此处指的是p是指向int类型的指针;

第二步:给指针变量赋值,也就是让指针指向另一个变量,当我们没有指定指针变量之前,这个指针不能被解引用;

p=&a //实现指针绑定,让p指向变量a

p=(int *)4 //实现指针绑定,让p指向地址为4的哪个变量

第三步:解引用

如果没有绑定指针到某个变量就直接解引用,基本一定会出错。

*p=555 //将555放入p指向的变量中

第二点:

野指针是什么

(1)也就是指针被指向的位置是不可知的(随机的、不正确的、没有明确限制的)

(2)野指针运行时可能触发运行时段错误(sgmentation fault)

(3)野指针可能带来三种后果:

指针指向不可访问的内核地址,触发段错误信息,这种算比较好的;

指针指向没什么特别意义的地址空间(譬如我们以前使用过,但是现在已经释放不使用了)这种情况不会报错,不会出现问题,但其实是有问题的;

指针指向了一个正在运行的代码所指向的地址,导致这个变量被离奇的改变,程序出现错误;

如何避免野指针

野指针的错误来源就是指针定义了以后没有初始化,也没有赋值(没有指向一个可用的内存空间),然后去解引用;

解决方法:在解引用之前,一定确保指针指向一个绝对有用的空间;

常规做法:定义指针时,同时初始化NULL;在指针解引用之前,先去判断这个指针是不是NULL;指针使用完之后,将其赋值为NULL;在使用指针前,将其赋值绑定给一个可用的地址空间;

第三点:

const关键字与指针

const关键字,在C语言中用来修饰变量,表示这个变量是常量。 const只能修饰一个变量;

p与*p是两个变量,因此const修饰可能会理解错误,常见如下:

在某些单片机中,const修饰的变量是不能修改的,但在gcc中,如果骗过编译这块,他是可以改 可以运行的;

第四点:

数组中几个关键符号的理解

前提:int a[10]

a做右值时等同于数组a中首元素的首地址;a不能做左值;

a[0]做左值时代表数组第0个元素所对应的内存空间(连续4字节),做右值时代表第0个元素的值;

&a本质是一个常量,因此不能做左值,做右值时代表的是整个数组的首地址,也等同于&a[0], 结果相同,但是意义不同;

&a[0]字面意思就是数组第0个元素的首地址,做左值时便是数组首元素对应的内存空间,做右值时表示数组首元素的首地址,做右值时&a[0]等同于a;

 指针和数组类型匹配的问题:

int *p;  int a[5];      p=a;   //类型匹配   

int *p;  int a[5];      p=&a; //类型不匹配

p是int * 类型,&a是整个数组的指针,也就是一个数组指针类型,不是int指针类型,所以不匹配

&a、a、&a[0]从数值上来看相等的,但是意义来看就不同了。从意义上来看a和&a[0]是数组首元素地址,而&a是整个数组的首地址;从类型上来看,a和&a[0]是元素的指针,也就是int *类型;而&a是数组指针,是int(*)[5]类型;

第四点:

指针强制类型转换

说一下我看完这部分知识点之后的感受;指针他妈的真难,看了跟没看一样!!!

先简单做一下我初次看完之后的笔记,后面有感悟再来补。

强制转换过程中,同一类型的数据形式才能够互相转换,不同形式的转换一定出错;

比如整形: int  char  short   long   都是整形的,相互转换可能出错,可能不出错。一般在由占大字节的形式转换小字节的形式时,容易出错,因为会溢出; 由小字节的形式转换为大字节的过程中国不会出错;

不同形式:比如float和int转化一定出错;

第五点:

指针、数组和sizeof运算符、typedef与dpchar

sizeof用来判断当前变量/数据类型在当前环境下占几个字节;

strlen是一个C库函数,用来返回一个字符串长度(字符串长度不计算字符串末尾的“\0”

数组里面存字符串的时候,在字符最后其实还有一个“\0”所以sizeof(str)的字节长度是6个;

(1)char *p = str; sizeof(p)得到的永远是4,因为这时候sizeof测的是字符指针p本身的长度,和字符串的长度是无关的。
(2)strlen刚好用来计算字符串的长度

 

typedef与dpchar

第六点:

指针与函数传参

(1)普通变量作为函数形参

函数传参时,普通变量作为参数时,形参和实参名字可以相同也可以不同,实际上都是用

实参来代替形参;  

在子函数内部,形参等于实参,原因是函数调用时把实参的值赋值给了形参;

(2)数组作为函数形参

函数名作为形参传参时,实际传输的不是整个数组,而是数组首元素的首地址(也是这个数组的首地址,因为传参时是传值。所以这两个没区别)。

数组有两个特殊的性质。一是不能复制数组;二是使用数组名字时,数组会自动转化为指向其第一个元素的指针。

可以由整个数组当作函数的参数,也可以由数组中的某个元素当作函数的参数:

所以在子函数内部,传进来的数组名等于是一个指向数组首元素的指针。所以sizeof得到的是4   下面是子函数; 

数组作为函数传参时,[]里面的数字是可有可无的,为什么? 因为数组名做形参传输时是个指针,根本没有书写长度这个信息。

(3)指针作为函数形参

和数组作为函数形参是一样的,他指向的是实参的第一个元素的地址,所以形参本身是一个指针!所以打印出他的长度就是指针的长度,为4,具体参考Cplus的293页这个例子

(4)结构体作为函数形参

第七点:

指针中常使人混淆的知识点:

前提是: int a[];  int *p; p=a;

(1)p++; *p

p++是使p指向下一个元素a[1].然后再执行*P,则得到了下一个元素a[1]的值!

(2)*p++

由于*和++同优先级,结合方向为自右向左,因此它等价于*(p++),先引用p的值,实现*p的运算,然后再使p自增1

(3)*(p++)和*(++p)

前者是先用*再加1;后者是先加1再取*;

(4)++(*p)

表示p所指的元素加1;如果p=a,则++(*p)相当于++a[0],若a[0]的值为3,则在执行++(*p)后a[0]的值为4;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/587747
推荐阅读
相关标签
  

闽ICP备14008679号