如何学习指针(1)

开始学习前,先说明一下,下述所写代码均是伪代码哦。

1.记住这句话:指针==地址==内存单元的编号,指针就是用来存地址的。

2.取地址符(&)

int n;
&n;//通过取地址符&可以得到n的地址

3.指针变量和解引用操作符(*)

int *p=NULL://初始化指针变量p


//----------------------------

int a=10;
int *p=&a;//用指针变量p存放a的地址
printf("%d",*p);//p中存放的是a的地址,*p解引用得到a中的数据,即*p=10;


//值得补充的是,解引用可以修改指针指向的地址的内容,如上述可以*p=0,a的值也就为0了,可以运用在跨
//函数修改值的情况下


int a=10;
int *p=&a;//用指针变量p存放a的地址
*p=0;
printf("%d",a);//p中存放的是a的地址,*p解引用修改了a中的数据,即a==*p==0;

//-----------------------------------------

void test(int *p)    //跨函数的情况下
{
    *p=0;//*p将a中的值修改为0
}

int main()
{
int a=10;
test(&a);
printf("%d",a);//此时a==0;

4.指针变量的大小

无论什么类型的指针,如char *p;int *p;double *p。这些指针的大小但是相同的,在32位的操作系统下是4个字节的大小,在64位的操作系统下是8个字节的大小。

5.指针变量类型的意义

(1)解引用时不同

int n=0x11223344;

int *pa=&n;

*pa=0;

printf("%x",n);//n=0x00000000;

//--------------------------

int n=0x11223344;

char *pb=&n;

*pb=0;

printf("%x",n);//n=0x00223344;

(2)加减时不同

int n=10;//假设n的地址是0x00000001

int *pa=&n;
char *pb=&n;

printf("%p",&n);//&n=0x00000001;
printf("%p",pb+1);//pb+1=00000002;//指针类型决定了加减的大小,如char*加减1位,int*加减4位
printf("%p",pa+1);//pa+1=00000005;

(3)特殊指针类型(void*)

void*指针类型不能进行加减运算,也不能进行解引用运算,void*的指针该如何使用呢?

⼀般 void* 类型的指针是使⽤在函数参数的部分,⽤来接收不同类型数据的地址,这样的设计可以 实现泛型编程的效果。使得⼀个函数来处理多种类型的数据。处理时用强制类型转换即可。日后遇见就明白了。

6.const修饰指针

const说白了就是保持数据不变的作用。

//-----------------------------------------------

//第一种情况,const在*前

int n=0;
int *p=&n;
*p=10;//ture
printf("%d",n);//n被修改为10


int n=0;
const int *p=&n;
*p=10;//error,此时会报错,const修饰后,解引用只能是n=0,不能再修改
printf("%d",n);p

//-----------------------------------------------

//第二种情况,const在*后

int m=0;
int n=0;
int *p=&m;
p=&n;//ture
printf("%p",&m);
printf("%p",&n);
printf("%p",p);//p指向的是n的地址


int m=0;
int n=0;
int * const p=&m;
p=&n;//error,此时会报错,const修饰后,p只能指向m的地址,不能再指向其它的地址
printf("%p",&m);
printf("%p",&n);
printf("%p",p);

//-----------------------------------------------

//第三种情况,const既在*前,也在*后
//也就是前两种情况的结合,不能解引用修改值,也不能改变指向的地址,这里不再赘述。



//-----------------------------------------------

//补充不是指针的情况下
int n=0;
n=10;//ture

const int n=0;
n=10;//error,此时会报错,const修饰后,变量也不可更改


7.指针的运算

(1)加减运算:就是根据指针类型加减不同的大小,前面讲过,这里不再赘述。

(2)指针-指针:就是指针之间元素数目的差值,如是int*指针相减等于字节数/4,char*指针相减等于字节数/1,不同类型的指针不能相减,必须是相同类型的指针。

(3)指针大小的判断:&a=0x00000001,&b=0x00000002,&a<&b,根据指针指向的地址大小来判断。

8.野指针

(1)局部指针未初始化,默认为随机值。如:

#include <stdio.h>

 int main()
 { 
     int *p;//局部变量指针未初始化,默认为随机值,应当int *p=NULL;  
     *p = 20;  
     return 0;  
}

(2)越界访问

int a[10]={0};
int *p=a[10];//数组a只有a[0]到a[9],此时越界了

(3)指针指向的地址被释放

void stm()
{
    int a=10;
    return &a;
}

int main()
{
    int *p=stm();//a是局部变量,在stm()函数结束时已经被销毁了,&a已经不存在了
    return 0;
} 

9.野指针的避免

(1)初始化时给确切的地址或赋NULL

int *p=NULL;

//或者

int a=10;
int*p=&a;

(2)避免越界访问

(3)避免接受返回的局部变量的地址

(4)当用完指针时,习惯将指针置NULL,习惯使用指针时检查指针的有效性。

10.assert断言

assert(表达式),若表达式为假,系统会报错。常用于判断指针是否非空。若不需要,只需加宏定义#define NDEBUG即可,系统默认assert语句无效。所需头文件为assert.h。缺点就是多了代码,就多耗费时间。

博主本人也是菜鸟,这些是我学习后总结出来的知识点,希望可以帮到大家,大家互相学习,共同进步。欢迎大家指出错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值