指针运算——算术运算、关系运算

 是不是对指针的任何运算都是合法的呢?答案是它可以执行某些运算,但并非所有的运算都合法。除了加法运算之外,你还可以对指针执行一些其他运算,但并不是很多。

    指针加上一个整数的结果是另一个指针。问题是,它指向哪里?如果你将一个字符指针加1,运算结果产生的指针指向内存中的下一个字符。float占据的内存空间不止1个字节,如果你将一个指向float的指针加1,将会发生什么?它会不会指向该float值内部的某个字节呢?

   答案是否定的。当一个指针和一个整数量进行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整。这个“合适的大小”就是指针所指向类型的大小,“调整”就是把整数值和“合适的大小”相乘。为了更好的说明,试想在某台机器上,float占据4个字节。在计算float型指针加3的表达式时候,这个3将根据float类型的大小(此例中为4)进行调整(相乘),这样实际上加到指针上的整型值为12。

     把3与指针相加使指针的值增加3个float的大小,而不是3个字节。这个行为较之获得一个指向一个float值内部某个位置的指针更为合理。下表包含了一些加法运算的例子。调整的美感在于指针算法并不依赖于指针的类型。换句话说,如果p是个指向float的指针,那么p+1就指向下一个float,其他类型也是如此。

 1.算术运算

    C的指针的算术运算只局限于两种形式。第一种形式是:    指针+-整数  标准定义这种形式只能用于指向数组中某个元素的指针,如图所示:

并且这类表达式的结果类型也是指针。这种形式也适用于使用malloc函数动态分配获得的内存。

对一个指针加1使它指向数组中的下一个元素,加5使它向右移动5个元素的位置,依次类推。把一个指针减去3使它向左移动3个元素的位置。

第二种类型的指针运算具有如下的形式:   指针—指针

只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针,如下所示:

两个指针相减的结果的类型是ptrdiff_t,它是一种有符合整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度

如果两个指针所指向的不是同一个数组中的元素,那么它们之间相减的结果是未定义的。程序员无从知道两个数组在内存中的相对位置,如果不知道这一点,两个指针之间的距离就毫无意义。

2.关系运算:   <   <=   >   >=  不过前提是它们都指向同一个数组中的元素。根据你所使用的操作符,比较表达式将告诉你哪个指针指向数组中更前或更后的元素。标准并未定义如果两个任意的指针进行比较会产生什么结果。

转自:
http://www.cnblogs.com/candyming/archive/2011/11/26/2263090.html

[cpp]  view plain copy
  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     char a[20]=" You_are_a_girl";  
  5.     char *p=a;  
  6.     <span style="color:#FF0000;">char **ptr=&p;</span>  
  7.     //printf("p=%d\n",p);  
  8.     //printf("ptr=%d\n",ptr);  
  9.     //printf("*ptr=%d\n",*ptr);  
  10.     printf("**ptr=%c\n",**ptr);  
  11.     ptr++;  
  12.     //printf("ptr=%d\n",ptr);  
  13.     //printf("*ptr=%d\n",*ptr);  
  14.     printf("**ptr=%c\n",**ptr);  
  15. }  

误区一、输出答案为Y 和o

误解:ptr 是一个char 的二级指针,当执行ptr++;时,会使指针加一个sizeof(char),所以输出如上结果,这个可能只是少部分人的结果.

误区二、输出答案为Y 和a

误解:ptr 指向的是一个char *类型,当执行ptr++;时,会使指针加一个sizeof(char *)(有可能会有人认为这个值为1,那就会得到误区一的答案,这个值应该是4,参考前面内容), 即&p+4; 那进行一次取值运算不就指向数组中的第五个元素了吗?那输出的结果不就是数组中第五个元素了吗?答案是否定的.

正解: ptr 的类型是char **,指向的类型是一个char *类型,该指向的地址就是p的地址(&p),当执行ptr++;时,会使指针加一个sizeof(char*),即&p+4;那*(&p+4)指向哪呢,这个你去问上帝吧,或者他会告诉你在哪?所以最后的输出会是一个随机的值,或许是一个非法操作.

总结一下:

一个指针ptrold 加(减)一个整数n 后,结果是一个新的指针ptrnewptrnew 的类型和ptrold 的类型相同,ptrnew 所指向的类型和ptrold所指向的类型也相同。ptrnew 的值将比ptrold 的值增加(减少)了n 乘sizeof(ptrold 所指向的类型)个字节。就是说,ptrnew 所指向的内存区将比ptrold 所指向的内存区向高(低)地址方向移动了n 乘sizeof(ptrold 所指向的类型)个字节。

指针和指针进行加减:

两个指针不能进行加法运算这是非法操作,因为进行加法后,得到的结果指向一个不知所向的地方,而且毫无意义。两个指针可以进行减法操作,但必须类型相同,一般用在数组方面,不多说了


[cpp]  view plain copy
  1. #include<stdio.h>  
  2. int main()  
  3. {  
  4.     char a[20]=" You_are_a_girl";  
  5.     char *p=a;  
  6.     <span style="color:#FF0000;">char **ptr=&p;</span>  
  7.     //printf("p=%d\n",p);  
  8.     //printf("ptr=%d\n",ptr);  
  9.     //printf("*ptr=%d\n",*ptr);  
  10.     printf("**ptr=%c\n",**ptr);  
  11.     ptr++;  
  12.     //printf("ptr=%d\n",ptr);  
  13.     //printf("*ptr=%d\n",*ptr);  
  14.     printf("**ptr=%c\n",**ptr);  
  15. }  

误区一、输出答案为Y 和o

误解:ptr 是一个char 的二级指针,当执行ptr++;时,会使指针加一个sizeof(char),所以输出如上结果,这个可能只是少部分人的结果.

误区二、输出答案为Y 和a

误解:ptr 指向的是一个char *类型,当执行ptr++;时,会使指针加一个sizeof(char *)(有可能会有人认为这个值为1,那就会得到误区一的答案,这个值应该是4,参考前面内容), 即&p+4; 那进行一次取值运算不就指向数组中的第五个元素了吗?那输出的结果不就是数组中第五个元素了吗?答案是否定的.

正解: ptr 的类型是char **,指向的类型是一个char *类型,该指向的地址就是p的地址(&p),当执行ptr++;时,会使指针加一个sizeof(char*),即&p+4;那*(&p+4)指向哪呢,这个你去问上帝吧,或者他会告诉你在哪?所以最后的输出会是一个随机的值,或许是一个非法操作.

总结一下:

一个指针ptrold 加(减)一个整数n 后,结果是一个新的指针ptrnew,ptrnew 的类型和ptrold 的类型相同,ptrnew 所指向的类型和ptrold所指向的类型也相同。ptrnew 的值将比ptrold 的值增加(减少)了n 乘sizeof(ptrold 所指向的类型)个字节。就是说,ptrnew 所指向的内存区将比ptrold 所指向的内存区向高(低)地址方向移动了n 乘sizeof(ptrold 所指向的类型)个字节。

指针和指针进行加减:

两个指针不能进行加法运算,这是非法操作,因为进行加法后,得到的结果指向一个不知所向的地方,而且毫无意义。两个指针可以进行减法操作,但必须类型相同,一般用在数组方面,不多说了

指针++”和“指针--”表示指针所指地址的下一个或前一个数据的地址

    指针的算术运算一般都是在操作数组的时候进行,因为只有声明数组才可以得到连续的内存空间。如果我们对一个单独的变量地址进行加或减的算术运算,然后改变新地址的值,则可能会破坏该地址的数据,所以在对指针进行算术运算时要明确运算的结果是程序中分配可用的地址。

    指针的关系运算说的是相同类型的指针之间的关系运算。不同类型的指针之间的关系运算没有任何意义,指针和非0整数的关系运算也没有任何意义,但是指针可以和0进行关系运算,两个相同类型的指针相等,表示这两个指针指向同一个地址。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值