zoukankan      html  css  js  c++  java
  • C 温故知新 之 指针:基本概念&变量的指针和指向变量的指针

       再次拿起C是2012年8月1日,回想第一次接触C还是大一下学期,大约是2006年。。。。大学C期末考试时我仍记得C考了76分……那年要不是C完全是可以拿一等奖学金的  六年了 之前虽熟悉C但是没认认真真去看去练习只晓得去应付考试。现在拿起来再瞅瞅……

      《C语言_谭浩强》关于指针学习时有这么一句话“在学习中除了要正确理解基本概念,还必须要多编程,上机调试。只要作到这些,指针也是不难掌握的。” 另一层意思就是指针还是很难滴 。。

    1.地址指针的基本概念

       指针定义:通俗的说就是一个地址(常量)。书中定义:根据内存单元的编号或地址找到相应的内存单元

    “看图识字”: 设有字符变量 C,其内容为“K”(ASCII 码为十进制数 75),C 占用了011A 号单元(地址用十六进数表示)。设有指针变量 P,内容为 011A,这种情况我们称为 P 指向变量 C,或说 P 是指向变量 C 的指针

      定义指针的目的:通过指针去访问内存单元。

    2.变量的指针和指向变量的指针变量

       变量的指针就是变量的地址。存放变量地址的变量是指针变量。即在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个变量的地址或称为某变量的指针。

    为了表示指针变量和它所指向的变量之间的关系,在程序中用“*”符号表示“指向”, eg:i_pointer 代表指针变量,而*i_pointer是i_pointer 所指向的变量。

      i=3;
      *i_pointer=3;
      第二个语句的含义是将 3 赋给指针变量 i_pointer 所指向的变量。

      A.定义一个指针变量

      格式:类型说明符  *变量名;

      *表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。

      例如:    int *p1;

      表示 p1 是一个指针变量, 它的值是某个整型变量的地址。 或者说 p1 指向一个整型变量。至于 p1 究竟指向哪一个整型变量,应由向 p1 赋予的地址来决定。

     B.指针变量的引用

      注意:1、指针不仅要先定义说明,而且必须赋予具体的值 如果现在还不是很清楚这句话等下下面有案例。

         2、指针变量的赋值只能赋予地址,决不能赋予任何其它数据。

           3、不允许把一个数赋予指针变量 eg:int *p; p=1000;//错误

         4、被赋值的指针变量前不能再加“*”说明符 eg: *p=&a//错误 正确:p=&a

      正确的初始化赋值方式:int a;int *p=&a;OR int a;int *p; p=&a;

    eg:

     

    注意:程序第 5、6 行的“pointer_1=&a”和 “pointer_2=&b”不能写成“*pointer_1=&a”和 “*pointer_2=&b”。

      请对下面再的关于“&”和“*”的问题进行考虑:
        1)  如果已经执行了“pointer_1=&a;”语句,则&*pointer_1 是什么含义?  等价&a
        2)  *&a 含义是什么?  等价*pointer_a
        3)  (pointer_1)++和pointer_1++的区别?经运行得到的值如下图:

     C.指针变量作为函数参数

    swap(int *p1,int *p2) 
    {
          int temp; 
          temp=*p1; 
          *p1=*p2; 
          *p2=temp; 
    } 
    
    main()
    {
             int a,b; 
         int *pointer_1,*pointer_2; 
         scanf("%d,%d",&a,&b); 
         pointer_1=&a;pointer_2=&b; 
         if(a<b) swap(pointer_1,pointer_2); 
          printf("\n%d,%d\n",a,b); 
    }

    结果就是用户输入的值比较大小,当然了要求是int类型你要是输入其他类型那么对不起咱得到的结果可能就是不是你所期望的。。。

    书上的解释“对程序的说明: swap 是用户定义的函数,它的作用是交换两个变量(a 和 b)的值。swap 函数的形参p1、p2 是指针变量。程序运行时,先执行 main函数,输入 a 和b 的值。然后将 a 和b 的地
    址分别赋给指针变量 pointer_1和 pointer_2,使pointer_1 指向 a,pointer_2 指向b。接着执行 if 语句,由于 a〈b,因此执行 swap 函数。注意实参 pointer_1 和 pointer_2 是指针变量,在函数调用时,将实参变量的值传递给形参变量。采取的依然是“值传递”方式。因此虚实结合后形参 p1 的值为&a,p2 的值为&b。这时 p1 和 pointer_1 指向变量 a,p2 和pointer_2 指向变量b。”

     

    上面我们有提供指针不但要定义还要初始化,看看下面例子

    swap2(int *p1,int *p2)
    {
        int *temp;
        *temp=*p1;
        *p1=*p2;
        *p2=*temp;
    }

    看看运行结果:

    原因就是指针temp没有赋值。。赋一个值 “ int i=0 ; int *temp=&i;” 问题解决……

     

    注意:不能企图通过改变指针形参的值而使指针实参的值改变[这句话还有点糊糊我]


    看看书上图怎么解释的:其中的问题在于不能实现如图所示的第四步(d)

     

     D. 指针变量几个问题的进一步说明

    1.  指针运算符

      1、指针变量只能进行赋值运算和部分算术运算及关系运算

      2、取地址运算符&:取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址

      3、取内容运算符*:取内容运算符*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量

      4、指针运算符*和指针变量说明中的指针说明符*不是一回事

          指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型

          表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量

    2.  指针变量的运算

      1、指针变量初始化赋值

      2、把一个变量的地址赋予指向相同数据类型的指针变量

        例如:
          int a,*pa;
          pa=&a;    /*把整型变量a 的地址赋予整型指针变量 pa*/

      3、把一个指针变量的值赋予指向相同类型变量的另一个指针变量

          例如:
            int a,*pa=&a,*pb;
            pb=pa;    /*把a 的地址赋予指针变量 pb*/{由于 pa,pb均为指向整型变量的指针变量,因此可以相互赋值}

      4、把数组的首地址赋予指向数组的指针变量

          例如:
            int a[5],*pa;
            pa=a;
            (数组名表示数组的首地址,故可赋予指向数组的指针变量 pa)
          也可写为: 当然你也可以赋值&a[1]、&a[2]……
            pa=&a[0];  /* 数组第一个元素的地址也是整个数组的首地址,也可赋予 pa */

          当然也可采取初始化赋值的方法:
            int a[5],*pa=a;

      5、把字符串的首地址赋予指向字符类型的指针变量

         例如:
            char *pc;
            pc="C Language";
          或用初始化赋值的方法写为:
            char *pc="C Language";

         注意:不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量

      6、把函数的入口地址赋予指向函数的指针变量
         例如:
            int (*pf)();
            pf=f;     /*f 为函数名*/

     

     

    最后整两个练习:

    main()
    {    
        int a,b,c,*pmax,*pmin;
        printf("input three numbers:\n");
        scanf("%d%d%d",&a,&b,&c);
        if(a>b)
        {
            pmax=&a;
            pmin=&b;
        }
        else
        {
            pmax=&b;
            pmin=&a;
        }
        if(c>*pmax)
        {
            pmax=&c;
        }
        else
        {
            pmin=&c;
        }
        printf("max=%d\nmin=%d\n",*pmax,*pmin);
    }
    main()
    {
        int a=10,b=20,s,t,*pa,*pb;
        pa=&a;
        pb=&b;
        s=*pa+*pb;
        t=*pa**pb;
        printf("a=%d\nb=%d\na+b=%d\na*b=%d\n",a,b,a+b,a*b);
        printf("s=%d\nt=%d\n",s,t);
    }

    案例一结果:

    案例二结果:

     


    作者:PEPE
    出处:http://pepe.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


    作者:PEPE
    出处:http://pepe.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    代码 技术债务 打分
    C++ boost coroutine
    什么是 Python Django Flask &Tornado
    Quartz应用与集群原理分析
    和开源产品对比
    Apache Storm || Processing real-time data
    认清自我,不在迷茫 程序员
    快速傅里叶变换算法
    Netty和Tomcat的区别、性能对比
    HTTP vs. MQTT ->TCP
  • 原文地址:https://www.cnblogs.com/PEPE/p/2628042.html
Copyright © 2011-2022 走看看