当前位置:   article > 正文

深入理解C语言指针操作的技巧与要点

*p, p=4

C语言指针的操作确实让我琢磨不透,调试了一下午之后,好像明白是怎么回事了,写个博文记录一下吧,怕忘记了。

一、前置++与后置++

首先,我们来研究一下前置++ 和后置++的区别。

++在前,先增再用。

void main()

{

int a = 1;

int b = ++a+1;//++运算符优先于+号,所以先计算++a,++在前,先增再用,a自增为2,再与后面的1进行运算 b=2+1=3

printf("b=%d,a=%d", b, a);

}

运行结果

eb2a0c98d1cd4da1be34d98b61eb346c.png

++在后,先用后增。

代码示例:

#include

void main()

{

int a = 1;

int b = 1+a++; //++运算符优先于+号,所以先算a++,又因为++在后面,所以先把a用掉,就是先计算1+a,a=1所以1+a=2,然后a再自增。a也变成了2。

printf("b=%d,a=%d",b,a);

}

运行结果

4ca03405457da55c005739f589ae2672.png

前置- -和后置- -与加一样,–在前面,先自减,再计算,–在后面先计算在自减。

前置- -先自减再用

void main()

{

int a = 1;

int b = --a + 1;//--在前,先自减,再运算,a自减为0,再计算 b=0+1=1

printf("b=%d,a=%d", b, a);

}

运行结果

8867bb8a2fef54dd3fbd238b9fb8adca.png

后置- -先用再自减

void main()

{

int a = 1;

int b = 1 + a--;//--运算符优先于-号,所以先算a--,又因为--在后面,所以先把a用掉,就是先计算1+a,a=1所以1+a=2,然后a再自减,a变成了0。

printf("b=%d,a=%d", b, a);

}

运行结果

e15f5816063f4cbd97f7b9aa57b8d546.jpg

二、*p和p,指针指向的内存空间,和指针地址

p就是一个指针,保存的是地址,*p是操作指针所指向的内存空间。

指针指向谁,就把谁的地址赋值给指针

假如我有一个变量a=100; 然后定义一个指针,让他指向变量a的内存空间。

如图:

147a26848d78498bea7b0a1f66309db1.png

#include

void main()

{

int a = 100; //定义变量a

int* p;//定义指针p

p = &a;//指针指向a(就是把a)的地址给指针,所以a要取地址。

printf("p=%p,&a=%p", &a, p);//可以看出来指针的地址和变量的地址是一样的

可以看到他们俩的结果是一样的。p和a是同一块内存空间

2ea0b954d1b54735881f715a9c4c6df3.png

假如下面我操作*p,就是在改变变量a的值。

#include

void main()

{

int a = 100; //定义变量a

int* p;//定义指针p

p = &a;//指针指向a(就是把a)的地址给指针,所以a要取地址。

printf("p=%p,&a=%p", &a, p);//可以看出来指针的地址和变量的地址是一样的

*p = 10;//*p操作指针所指向的内存空间,也就是a的值。通过指针把a的值改成了10

printf("这是通过*p操作之后的a=%d\n",a);

3f218522ce7c422a847c6f12068f76db.jpg

讨论完了指针,我们来讨论

三、开始讨论 *++p,++*p,*p++,(*p)++,*(p++)

*和++属于同一级运算符,结合方向是从右至左

(一)、*++p 按照从右到左的结合顺序,我们是不是应该先算++p(p和++结合是地址自增),然后再取*,取*就是取指针所指向的内存空间。

代码示例:

int arr[3] = { 1,4,6 };//定义了一个数组,3个元素

int* p = arr;//将指针指向素组首元素地址,数组名就是首元素地址,所以不用取地址了

printf("执行前的地址为:%p\n", p); //执行语句以前打印一哈p的地址

int a = *++p;//执行语句

printf("执行后的地址为%p\n", p);//这是执行语句以后的地址

printf("*++p=%d\n", a)//打印*++p的结果

5a216d9b711aa6202a184665e3d88280.png

代码分析:可以看到,执行后的地址比执行前的地址多了4,因为一个int类型的占是4个字节,所以执行后的地址为00f8fe48, 地址先增加了4个,所以指针的指向就跳到了素组的第二个元素,然后再取*,所以就打出了p++=4,所以可以看到先执行了p++让地址增加1个(增加一个是占用的是4个字节的空间),然后再运算打印指针所指向的内存空间。

画图分析

88b080807fb74201b0fec3c906ed1bdc.png

(二)、++*p 按照从右到左的结合顺序,我们是不是应该先算*p,再计算++。

代码示例

int arr[3] = { 1,4,6 };

int* p = arr;//将指针指向素组首元素地址,数组名就是首元素地址,所以不用取地址了

printf("执行前的地址为:%p\n", p);

int a = ++ *p;

printf("执行前的地址为:%p\n", p);

printf("数组的第一个元素:%d\n", arr[0]);//这一步是验证指针改变了数组元素的值。执行 ++ * p后,数组的首元素的值也发了变化。

printf("++*p=%d\n", a);

294760fe998f40df90c45330c5366944.png

本例中,先*p取值是1,++在前,所以先计算++ , *p的计算结果是1,再++的结果就变成了2,然后再用a打印出来。通过指针操作了素组的首元素的值也变成了2。地址没有发生变化。

画图理解

41a1a386dc134a18661a3977277e1fd3.png

(三)、*p++ 按照从右到左的结合顺序,先算p++,又因为++在后,所以先把p用掉和*进行结合运算后再增,用掉以后p的地址还是原来的地址(此时还没有进行自加)当计算完*p之后,p的地址+1。

代码示例:

int arr[3] = { 1,4,6 };

int* p = arr;

printf("执行前的地址为:%p\n", p);

int a = *p++;

printf("执行前的地址为:%p\n", p);

printf("*p++=%d\n", a);

81baf214499449978ce6e005e15f499d.png

代码分析:本例中,从右到左,先计算p++,++在后,先用在增,p先和*结合,计算*p,p存的是数组的首元素地址,所以*p的值是1,所以打印的结果*p++是1,计算完*p之后,p再++,就是地址自加,指向就变成了数组的第二个元素。由原来的0093f910增加到009f914。

画图分析:

2cb79849b9554d7f9aaa0cf53b6d6139.png

(四)、(*p)++ :有括号先算括号里面的,在进行++。

int arr[3] = { 1,4,6 };

int* p = arr;

printf("执行前的地址为:%p\n", p);

int a = (* p)++;

printf("执行前的地址为:%p\n", p);

printf("(* p)++=%d\n", a);

cdb398032dbea40b15ff92c95c996fc2.png

代码分析:本例中,有括号先算括号里的,p指向的是arr[0]的地址,所以*p=1,++在后,所以先用在自增,先用就是先赋值给a,在++,所以打印出来的结果是1而不是2。

五、*(p++):有括号先算括号,所以先执行p++,又因为++在后,所以先用再自加,(和*p++是一样的顺序)p先和*进行结合,然后地址再++。

代码:

int arr[3] = { 1,4,6 };

int* p = arr;

printf("执行前的地址为:%p\n", p);

int a = *(p++);

printf("执行前的地址为:%p\n", p);

printf("*(p++)=%d\n", a);

7dd337e0ed5feb66bac7f1b0cda32b85.png

代码分析和*p++基本是一样的(有括号先括号)

六、++(*p):有括号先括号,先计算*p,然后++在前,先增再用。

代码:

int arr[3] = { 1,4,6 };

int* p = arr;

printf("执行前的地址为:%p\n", p);

int a = ++(*p);

printf("执行前的地址为:%p\n", p);

printf("++(*p)=%d\n", a);

81bbda758ebf6f19ac47a476f74786a6.png

分析:本例中,有括号先括号,先计算*p,*p是1,然后++在前,先增再用。所以++(*p)的结果是2

(七)*(++p) 有括号先括号,先算++p,++在前,所以先++,地址自增后再进行*运算。和*++p是一样的顺序。

代码:

int arr[3] = { 1,4,6 };

int* p = arr;

printf("执行前的地址为:%p\n", p);

int a = *(++p);

printf("执行前的地址为:%p\n", p);

printf("*(++p)=%d\n", a);

b3c5c577b34b4e9ecbee88d311a68c0e.png

分析:本例中,*(++p)先算括号里面的++p ,++在前,所以地址先做自增,再取*,所以打印的是数组的第二个元素,a[1]也就是4。

以上就是对于这几个代码的分析

C语言学习真的是不能靠看懂,要亲自动手调试,画图才能更好的理解。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号