【C语言】指针运算—— 算术运算,关系运算

算术运算

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

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

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

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

这里写图片描述

C的指针的算术运算只局限于两种形式。

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

这里写图片描述

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

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

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

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

这里写图片描述

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

这里写图片描述

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

举个例子:

#include <stdio.h>

int main(){
    int    a = 10,   *pa = &a;
    double b = 99.9, *pb = &b;
    char   c = '@',  *pc = &c;
    //最初的值
    printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c); //存储空间的地址值 
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);//指针的值 
    //加法运算
    pa += 1; pb += 1; pc += 1;
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc); //int4个字节,double为2个字节,char为1个字节 
    //减法运算
    pa -= 2; pb -= 2; pc -= 2;
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
    return 0;
}

这里写图片描述

同一个数组中两个指针相减例子:

#include<stdio.h>

int main()
{
    int a[10] = { 3,5,2,6,4,3,6,4,3 };
    int *s = &a[3], *f = &a[7];
    printf("*f-*s=%d", f - s);
 }

这里写图片描述

关系运算:

只有当两个指针指向同一个数组中的元素时,才能进行关系运算。
当指针p和指针q指向同一数组中的元素时,
则: (可以用在if判断里面作为条件)

p<q 当p所指的元素在q所指的元素之前时,表达式的值为1;反之为0。 
P>q 当p所指的元素在q所指的元素之后时,表达式的值为1;反之为0。 
p==q 当p和q指向同一元素时,表达式的值为1;反之为0。 
p!=q 当p和q不指向同一元素时,表达式的值为1;反之为0。

举例:

编写程序将一个字符串反向。

 #include <stdio.h> 

    void main( ) 
    { 
        char str[50], *p, *s, c; 

        printf("Enter string:"); 
        gets(str); //从键盘输入字符 

        p=s=str;  //将指针初始化 

        while ( *p ) 
        { 
            p++;  //将p指向字符串最后 
        }

            p--;//将p指针指向最后一个字符,原来指向最后一个的后面 

        while ( s<p )  // 判断地址 
        {
             c = *s;  
            *s++ = *p;  
            *p-- = c;  
        } 

        puts(str); 

下面是分步调试的结果:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

  • 14
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘星燎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值