zoukankan      html  css  js  c++  java
  • [转] 解读C指针(4)——指针运算

    原文地址:http://blog.csdn.net/czmpersist/article/details/11845533

         前面已经讲述了指针在内存中的存储,指针类型的定义,指定关键的概念(指针类型、指针所指向的类型、指针的值、指针本身所占据的内存区),在这一节中主要讲解指针的运算。


    指针的运算

    一、  算术运算

              指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的,而是以单元为单位。那什么是单元呢?请看下面的例子:

    char a[20];

    int *ptr=(int *)a;       //强制类型转换不改变a的类型

    ptr++;

           在上例中,指针ptr的类型是int*,它指向的类型是 int,它被初始化为指向整型变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在 32位程序中,是被加上了 4,因为在 32 位程序中,int占4字节。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4字节。由于 char 类型的长度是1字节,所以,原来ptr 是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。(认真体会这段话哦)。

           也许你还在苦恼,到底怎么回事?那请继续看下面的例子:

    char a[20]="You_are_a_girl";

     int *ptr=(int *)a;

    ptr+=5;

             在这个例子中,ptr 被加上了 5,编译器是这样处理的:将指针 ptr 的值加上 5 * sizeof(int),在 32 位程序中就是加上了 5 * 4=20。由于地址的单位是字节,故现在的ptr 所指向的地址比起加 5 后的 ptr 所指向的地址来说,向高地址方向移动了20字节。在这个例子中,没加5 前的 ptr 指向数组 a 的第 0 号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。

             如果上例中,ptr 是被减去 5,那么处理过程大同小异,只不过ptr的值是被减去 5 乘 sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20字节。到现在为止理解了吧!

    二、  运算符&和*

                 这里&是取地址运算符,*是间接运算符。

            &a 的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。

             *p的运算结果就各式各样了。总之*p的结果是p所指向的东西,这个东西有这些特点:*p类型是p指向的类型所占用的地址是p所指向的地址。(有点绕,还是理解前面关键的概念哦)。

    例:

    int a=12;  intb;  int *p;  int **ptr;

    p=&a;         

          解析:&a的结果是一个指针,类型是int*,指向的类型是int ,指向的地址是 a 的地址。

     *p=24;       

    解析:*p 的结果,在这里它的类型是 int,它所占用的地址是p所指向的地址,显然,*p 就是变量 a。

     ptr=&p; 

    解析:&p 的结果是个指针,该指针的类型是 p 的类型加个*,在这里是 int **。该指针所指向的类型是 p的类型,这里是 int*。该指针所指向的地址就是指针p自己的地址。

     *ptr=&b;      

    解析:*ptr 是个指针,&b 的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以用&b 来给*ptr 赋值就是毫无问题的了。

            **ptr=34;   

    解析:*ptr 的结果是 ptr 所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果是一个 int 类型的变量。

    三、  指针表达式

            一个表达式的结果如果是一个指针,那么这个表达式就叫指针表式。

            下面是一些指针表达式的例子:

    例:

    char a;

    char *ptr = &a;

    char *arr[20];

    char **parr=arr;          //如果把 arr 看作指针的话,arr 也是指针表达式

    char *str;

    str=*parr;               //*parr 是指针表达式

    str=*(parr+1);          //*(parr+1)是指针表达式

    str=*(parr+2);          //*(parr+2)是指针表达式

            由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。

            一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。上例中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是变量a,既然a已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。


             好了,今天指针运算就暂时讲到这里吧,这些在C语言书籍里面都有讲到,大家还是要好好回味下。

  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/minghang/p/5614472.html
Copyright © 2011-2022 走看看