当前位置:首页 » 编程语言 » c语言中指针加减问题求解
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

c语言中指针加减问题求解

发布时间: 2022-02-28 02:39:05

1. c语言指针相减报错的问题

C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别

1.一个实例+理论分析

在了解数组和指针的访问方式前提下,下面再看这个例子:

123456main(){inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));}

打印出来的值为多少呢? 这里主要是考查关于指针加减操作的理解。


对指针进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1。所 以,一个类型为T的指针的移动,以sizeof(T) 为移动单位。

因此,对上题来说,a是一个一维数组,数组中有5个元素,所以a的类型是数组指针;ptr是一个int 型的指针,ptr的类型是整型指针。

1&a +1:取数组a 的首地址,该地址的值加上sizeof(a) 的值,即&a +5*sizeof(int),也就是下一个数组的首地址。

显然当前指针已经越过了数组的界限。


(int *)(&a+1): 则是把上一步计算出来的地址,强制转换为int * 类型,赋值给ptr。

*(a+1):a,&a的值是一样的,但意思不一样,a是数组首元素的首地址,也就是a[0]的首地址,&a是数组的首地址,a+1是数组下一元素的首地址,即a[1]的首地址,&a+1是下一个数组的首地址。

所以输出2*(ptr-1):因为ptr是指向a[5],并且ptr是int * 类型,所以*(ptr-1)是指向a[4],输出5。

2.Visual C++6.0上的真实调试结果


这些分析我相信大家都能理解,但是在授课时,学生向我(陈正冲老师)提出了如下问题:


在Visual C++6.0的Watch窗口中&a+1的值怎么会是(x0012ff6d(0x0012ff6c+1)呢?

上图是在Visual C++6.0调试本函数时的截图。

123a在这里代表是的数组首元素的地址即a[0]的首地址,其值为0x0012ff6c。&a代表的是数组的首地址,其值为0x0012ff6c。a+1的值是0x0012ff6c+1*sizeof(int),等于0x0012ff70。


问题就是&a+1的值怎么会是(x0012ff6d(0x0012ff6c+1)呢?


按照我们上面的分析应该为0x0012ff6c+5*sizeof(int)。其实很好理解。当你把&a+1放到Watch窗口中观察其值时,表达式&a+1已经脱离其上下文环境,编译器就很简单的把它解析为&a的值然后加上1byte。而a+1的解析就正确,我(陈正冲老师)认为这是Visual C++6.0的一个bug。既然如此,我们怎么证明证明&a+1的值确实为0x0012ff6c+5*sizeof(int)呢?

很好办,用printf函数打印出来。这就是我在本书前言里所说的,有的时候我们确实需要printf函数才能解决问题。你可以试试用printf("%x",&a+1);打印其值,看是否为0x0012ff6c+5*sizeof(int)。注意如果你用的是printf("%d",&a+1);打印,那你必须在十进制和十六进制之间换算一下,不要冤枉了编译器。

另外我(陈正冲老师)要强调一点:不到非不得已,尽量别使用printf函数,它会使你养成只看结果不问为什么的习惯。比如这个列子,*(a+1)和*(ptr-1)的值完全可以通过Watch窗口来查看。平时初学者很喜欢用“printf("%d,%d",*(a+1),*(ptr-1));”这类的表达式来直接打印出值,如果发现值是正确的就欢天喜地。这个时候往往认为自己的代码没有问题,根本就不去查看其变量的值,更别说是内存和寄存器的值了。(嗯,这个坏习惯,我是有的。)

3. 最好不要利用printf函数进行调试

陈正冲老师的经验与教诲:

更有甚者,printf函数打印出来的值不正确,就措手无策,举手问“老师,我这里为什么不对啊?”。长此以往就养成了很不好的习惯,只看结果,不重调试。这就是为什么同样的几年经验,有的人水平很高,而有的人水平却很低。其根本原因就在于此,往往被一些表面现象所迷惑。printf函数打印出来的值是对的就能说明你的代码一定没问题吗?我看未必。曾经一个学生,我让其实现直接插入排序算法。很快他把函数写完了,把值用printf函数打印出来给我看。我看其代码却发现他使用的算法本质上其实是冒泡排序,只是写得像直接插入排序罢了。等等这种情况数都数不过来,往往犯了错误还以为自己是对的。所以我平时上课之前往往会强调,不到非不得已,不允许使用printf函数,而要自己去查看变量和内存的值。学生的这种不好的习惯也与目前市面上的教材、参考书有关,这些书甚至花大篇幅来介绍scanf和printf这类的函数,却几乎不讲解调试技术。甚至有的书还在讲TruboC 2.0之类的调试器!如此教材教出来的学生质量可想而知。

2. C语言指针运算问题

*q++

*(q++)是一样的
没错,括号是会提高优先级,但是对于q++这个自加运算是没有作用的.后置的++做自加运算都是等当前语句处理完了才自加1的.所以*(q++)可以看成是
*(q);
q=q+1;
可以看出括号只括着q...这样的括号其实是并没有提高任何优先级的...

3. c语言指针变量之间可以进行加减运算

可以啊指针其实也是一个内存单元,存放了一个地址,变量也是一个内存单元,存放了一个变量。减了就是吧指针这个内存单云存放的地址减了。

4. C语言两个指针相减的问题

虽然地址是随机的,因为数组从首地址开始依次相连


#include<stdio.h>
intmain()
{
chara[10];
char*b=&a[2];
char*p=&a[8];
printf("a[0]=%d ",&a[0]);//若a[0]地址为1000
printf("a[10]=%d ",&a[10]);//a[10]的地址就为1000+10
printf("a[2]=%d ",&a[2]);//所以a[2]为1000+2
printf("a[8]=%d ",&a[8]);//a[8]为1000+8
printf("%d",b-p);//a[2]-a[8]就等于1002-1008=-6
return0;
}

看看这段代码,希望能帮助你,望采纳

5. C语言 指针的减法 小问题

数组名 就代表数组的首地址,相当于一个地址常量
char *p=str; 这句是定义一个指针变量p,并将str的值(地址)赋值给p,这样p就指向str所在的数据了。

这句表示两层意思
1、char *p ; 定义指针变量
2、p=str;注意不是*p=str! 将str值赋值给p
是指针定义并初始化的样子。

6. C语言数组指针相减问题

age+1-age=1;
这里的1就是单纯的数字1,没有别的含义,所以结果是1

而第二个就不同了
(int)(age+1)-(int)(age)=4
这里加1是指,指针向后移动一个单位,单位是多少呢?
由于定义的是int型,在32位机中,int占4个字节,即一个单位=4字节

楼主若还不清楚,可以hi我

7. 关于c语言中的指针运算问题,求指教

#include<stdio.h>
main()
{
int k=2,m=4,n=6,*pk=&k,*pm=&m,*p;
p=&n ; //&是取变量地址的操作符,本句意思是将变量n所在的地址存储在p中。pm,pk同理。
*p=*pk * (*pm); //*是操作地址单元的操作符,*p就是相当于使用n(因为p是n的地址) , 同理pk , pm
printf("%d\n",n); //n=k*m=2*4=8 ;原来的6被覆盖了
}

8. 计算机c语言,指针与整数的加减法问题,

因为double是双精度类型,站8个字节。所以是5*8
满意请采纳! 追问可是书上写着占4个字节~~
这个根据你的CPU和系统来决定

9. c语言中指针加减问题,求解答。

首先:
float
a[10],*p,*q;
p=&a[4],q=&a[7];
那q-p=2(a[4]与a[7]之间有两个元素)
***这里就不对了,q-p
=
3
不是等于2,
可以用printf("%d",q-p);看看。
p+3-p
=
12
是地址按“字节”排列的位置差,表示p+3和p之间有12个字节
q-p
=
3
表示q和p之间有3个float类型的数据,每个占4字节,3x4
=
12
和上面的结果一致

10. 一个C语言指针自增自减的问题

如果放在第三个位置的话,那要等循环执行一次之后才会执行这个指针自减
出现那些数字,是因为在执行完上一个 for 循环之后,Ptr 已经到了数组外面去了,当然就会有随机数出来,那是其他内存区域的数据