博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C 温故知新 之 指针:基本概念&变量的指针和指向变量的指针
阅读量:6264 次
发布时间:2019-06-22

本文共 3776 字,大约阅读时间需要 12 分钟。

   再次拿起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

 

结果就是用户输入的值比较大小,当然了要求是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);}

 

案例一结果:

 

案例二结果:

 

 

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

你可能感兴趣的文章
视频会议
查看>>
EntityFramework系列:SQLite.CodeFirst自动生成数据库
查看>>
网络编码
查看>>
定时任务-在spring中配置quartz
查看>>
【springMVC 后台跳转前台】1.使用ajax访问的后台,后台正常执行,返回数据,但是不能进入前台的ajax回调函数中 ----2.前后台都没有报错,不能进入ajax回调函数...
查看>>
redis+Keepalived主从热备秒级切换
查看>>
Hibernate占位符警告:use named parameters or JPA-style positional parameters instead.
查看>>
基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化
查看>>
是什么时候开始学习gulp了
查看>>
【Cocos2d-x游戏开发】细数Cocos2d-x开发中那些常用的C++11知识
查看>>
otl使用存储过程或是LEFT JOIN时提示输出类型未知的问题
查看>>
集群(cluster)原理(转)
查看>>
小数格式:
查看>>
【MyBatis学习06】_parameter:解决There is no getter for property named in class java.lang.String...
查看>>
Eclipse导入别人的项目报错:Unable to load annotation processor factory 'xxxxx.jar' for project...
查看>>
与孩子一起学编程10章
查看>>
【再探backbone 03】博客园单页应用实例(提供源码)
查看>>
android 圆角编写(懒得去找,写给自己看的)
查看>>
chrome 搜索 jsonView
查看>>
chrome浏览器:chrome 69 恢复默认UI
查看>>