二级c语言辅导教程及考点分析:第六章指针


  第六章:指针

  指针简介

  指针是c言语中广泛使用的一种数据类型。 运用指针编程是c言语最次要的风格之一。 利用指针变量可以表示各种数据结构;能很方便地使用数组和字符串;并能象汇编言语一样处置内存地址, 从而编出精练而高效的顺序。 指针极大地丰富了c言语的功能。 学习指针是学习c言语中最重要的一环, 能否正确了解和使用指针是我们是否掌握c言语的一个标志。 同时, 指针也是c言语中最为困难的一部分, 在学习中除了要正确了解基本概念, 还必须要多编程, 上机调试。 只要作到这些, 指针也是不难掌握的。

  指针的基本概念在计算机中, 所有的数据都是寄存在存储器中的。 普通把存储器中的一个字节称为一个内存单元, 不同的数据类型所占用的内存单元数不等, 如整型量占2个单元, 字符量占1个单元等, 在第二章中已有详细的介绍。 为了正确地拜访这些内存单元, 必须为每个内存单元编上号。 依据一个内存单元的编号即可准确地找到该内存单元。 内存单元的编号也叫做地址。 既然依据内存单元的编号或地址就可以找到所需的内存单元, 所以通常也把这个地址称为指针。 内存单元的指针和内存单元的内容是两个不同的概念。 可以用一个粗浅的例子来阐明它们之间的关系。 我们到银行去存取款时, 银行任务人员将依据我们的帐号去找我们的存款单, 找到之后在存单上写入存款、取款的金额。 在这里, 帐号就是存单的指针, 存款数是存单的内容。 对于一个内存单元来说, 单元的地址即为指针, 其中寄存的数据才是该单元的内容。 在c言语中, 允许用一个变量来寄存指针, 这种变量称为指针变量。 因此, 一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。 中, 设有字符变量c, 其内容为“k”, c占用了011a号单元。 设有指针变量p, 内容为011a, 这种状况我们称为p指向变量c, 或说p是指向变量c的指针。 严格地说, 一个指针是一个地址, 是一个常量。 而一个指针变量却可以被赋予不同的指针值, 是变。 但在常把指针变量简称为指针。 为了防止混杂, 我们中商定:“指针”是指地址, 是常量, “指针变量”是指取值为地址的变量。 定义指针的目的是为了经过指针去拜访内存单元。

  既然指针变量的值是一个地址, 那么这个地址不只可以是变量的地址, 也可以是其它数据结构的地址。 在一个指针变量中寄存一

  个数组或一个函数的首地址有何意义呢?因为数组或函数都是延续寄存的。 经过拜访指针变量取得了数组或函数的首地址, 也就找到了该数组或函数。 这样一来, 凡是出现数组, 函数的地方都可以用一个指针变量来表示, 只要该指针变量中赋予数组或函数的首地址即可。 这样做, 将会使顺序的概念十分清楚, 顺序本身也精练, 高效。 在c言语中, 一种数据类型或数据结构往往都占有一组延续的内存单元。 用“地址”这个概念并不能很好地描画一种数据类型或数据结构, 而“指针”虽然实际上也是一个地址, 但它却是一个数据结构的首地址, 它是“指向”一个数据结构的, 因此概念更为清楚, 表示更为明确。 这也是引入“指针”概念的一个重要原因。

  指针变量的类型阐明

  对指针变量的类型阐明包括三个内容:

  指针类型阐明, 即定义变量为一个指针变量;

  指针变量名;

  变量值所指向的变量的数据类型。

  其普通形式类型阐明符变量名;

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

  例如:intp1;表示p1是一个指针变量, 它的值是某个整型变量的地址。 或者说p1指向一个整型变量。 至于p1终究指向哪一个整型变量, 应由向p1赋予的地址来决议。

  再如:

  staicintp2;/p2是指向静态整型变量的指针变量/

  floatp3;/p3是指向浮点变量的指针变量/

  charp4;/p4是指向字符变量的指针变量/应该留意的是, 一个指针变量只能指向同类型的变量, 如p3只能指向浮点变量, 不能时而指向一个浮点变量, 时而又指向一个字符变量。

  指针变量的赋值

  指针变量同普通变量一样, 使用之前不只要定义阐明, 而且必须赋予具体的值。 未经赋值的指针变量不能使用, 否则将形成系统混乱, 甚至死机。 指针变量的赋值只能赋予地址, 决不能赋予任何其它数据, 否则将引起错误。 在c言语中, 变量的地址是由编译系统分配的, 对用户完全通明, 用户不知道变量的具体地址。 c言语中提供了地址运算符来表示变量的地址。 其普通形式变量名;如a变示变量a的地址, b表示变量b的地址。 变量本身必须预先阐明。 设有指向整型变量的指针变量p, 如要把整型变量a的地址赋予p可以有以下两种方式:

  指针变量初始化的方法inta;

  intp=a;

  赋值语句的方法inta;

  intp;

  p=a;

  不允许把一个数赋予指针变量, 故下面的赋值是错误的:intp;p=1000;被赋值的指针变量前不能再加“”阐明符, 如写为p=a也是错误的

  指针变量的运算

  指针变量可以停止某些运算, 但其运算的种类是有限的。 它只能停止赋值运算和部分算术运算及关系运算。

  1。 指针运算符

  取地址运算符

  取地址运算符是单目运算符, 其结合性为自右至左, 其功能是取变量的地址。 在scanf函数及前面介绍指针变量赋值中, 我们已经了解并使用了运算符。

  取内容运算符

  取内容运算符是单目运算符, 其结合性为自右至左, 用来表示指针变量所指的变量。 在运算符之后跟的变量必须是指针变量。 需要留意的是指针运算符和指针变量阐明中的指针阐明符不是一回事。 在指针变量阐明中, “”是类型阐明符, 表示其后的变量是指针类型。 而表达式中出现的“”则是一个运算符用以表示指针变量所指的变量。

  main

  。 。 。 。 。 。

  表示指针变量p取得了整型变量a的地址。 本语句表示输出变量a的值。

  2。 指针变量的运算

  赋值运算

  指针变量的赋值运算有以下几种形式:

  ①指针变量初始化赋值, 前面已作介绍。

  ②把一个变量的地址赋予指向相反数据类型的指针变量。 例如:

  inta, pa;

  pa=a;/把整型变量a的地址赋予整型指针变量pa/

  ③把一个指针变量的值赋予指向相反类型变量的另一个指针变量。 如:

  inta, pa=a, pb;

  pb=pa;/把a的地址赋予指针变量pb/

  由于pa, pb均为指向整型变量的指针变量, 因此可以相互赋值。

  ④把数组的首地址赋予指向数组的指针变量。

  例如:inta, pa;

  pa=a;

  也可写

  pa=a;/数组第一个元素的地址也是整个数组的首地址,

  也可赋予pa/

  当然也可采取初始化赋值的方法:

  inta, pa=a;

  ⑤把字符串的首地址赋予指向字符类型的指针变量。 例如:charpc;pc=“clanguage“;或用初始化赋值的方法写charpc=“clanguage“;这里应阐明的是并不是把整个字符串装入指针变量, 而是把寄存该字符串的字符数组的首地址装入指针变量。 在前面还将详细介绍。

  ⑥把函数的入口地址赋予指向函数的指针变量。 例如:int;pf=f;/f为函数名/

  加减算术运算

  对于指向数组的指针变量, 可以加上或减去一个整数n。 设pa是指向数组a的指针变量, 则pa+n, pa-n, pa++, ++pa, pa--, --pa运算都是合法的。 指针变量加或减一个整数n的意义是把指针指向的当前位置向前或向后移动n个位置。 应该留意, 数组指针变量向前或向后移动一个位置和地址加1或减1在概念上是不同的。 因为数组可以有不同的类型, 各种类型的数组元素所占的字节长度是不同的。 如指针变量加1, 即向后移动1个位置表示指针变量指向下一个数据元素的首地址。 而不是在原地址根底上加1。

  例如:

  inta, pa;

  pa=a;/pa指向数组a, 也是指向a/

  pa=pa+2;/pa指向a, 即pa的值为pa/指针变量的加减运算只能对数组指针变量停止, 对指向其它类型变量的指针变量作加减运算是毫有意义的。 两个指针变量之间的运算只有指向同一数组的两个指针变量之间才干停止运算, 否则运算毫有意义。

  ①两指针变量相减

  两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。 实际上是两个指针值相减之差再除以该数组元素的长度。 例如pf1和pf2是指向同一浮点数组的两个指针变量, 设pf1的值为2010h, pf2的值为2000h, 而浮点数组每个元素占4个字节, 所以pf1-pf2的后果为/4=4, 表示pf1和pf2之间相差4个元素。 两个指针变量不能停止加法运算。 例如, pf1+pf2是什么意思呢?毫无实际意义。

  ②两指针变量停止关系运算

  指向同一数组的两指针变量停止关系运算可表示它们所指数组元素之间的关系。 例如:

  pf1==pf2表示pf1和pf2指向同一数组元素

  pf1pf2表示pf1处于洼地址位置

  pf1pf2表示pf2处于低地址位置

  main

  。 。 。 。 。 。

  阐明pa, pb为整型指针变量

  给指针变量pa赋值, pa指向变量a。

  给指针变量pb赋值, pb指向变量b。

  本行的意义是求a+b之和, 。

  本行是求ab之积。

  输出后果。

  输出后果。

  。 。 。 。 。 。

  指针变量还可以与0比拟。 设p为指针变量, 则p==0标明p是空指针, 它不指向任何变量;p!??表示p不是空指针。 空指针是由对指针变量赋予0值而得到的。 例如:对指针变量赋0值和不赋值是不同的。 指针变量未赋值时, 可以是恣意值, 是不能使用的。 否则将形成意外错误。 而指针变量赋0值后, 则可以使用, 只是它不指向具体的变量而已。

  main

  else

  ifpmax=c;

  ifpmin=c;

  printf;

  ??br/>
  。 。 。 。 。 。

  pmax, pmin为整型指针变量。

  输入提示。

  输入三个数字。

  如果第一个数字大于第二个数字...

  指针变量赋值

  指针变量赋值

  指针变量赋值

  指针变量赋值

  判断并赋值

  判断并赋值

  输出后果

  。 。 。 。 。 。

  数组指针变量的阐明和使用

  指向数组的指针变量称为数组指针变量。 在讨论数组指针变量的阐明和使用之前, 我们先明确几个关系。

  一个数组是由延续的一块内存单元组成的。 数组名就是这块延续内存单元的首地址。 一个数组也是由各个数组元素组成的。 每个数组元素按其类型不同占有几个延续的内存单元。 一个数组元素的首地址也是指它所占有的几个内存单元的首地址。 一个指针变量既可以指向一个数组, 也可以指向一个数组元素, 可把数组名或第一个元素的地址赋予它。 如要使指针变量指向第i号元素可以把i元素的首地址赋予它或把数组名加i赋予它。

  设有实数组a, 指向a的指针变量为pa, 从6。 3中我们可以看出有以下关系:

  pa, a, a均指向同一单元, 它们是数组a的首地址, 也是0号元素a的首地址。 pa+1, a+1, a均指向1号元素a。 类推可知a+i, a+i, a

  指向i号元素a。 应该阐明的是pa是变量, 而a, a都是常量。 在编程时应予以留意。

  main

  printf;

  ??br/>
  主函数

  定义一个整型数组和一个整型变量

  循环语句

  给数组赋值

  打印每一个数组的值

  。 。 。 。 。 。

  输出换行

  。 。 。 。 。 。

  数组指针变量阐明的普通形式

  类型阐明符指针变量名

  其中类型阐明符表示所指数组的类型。 从普通形式可以看出指向数组的指针变量和指向普通变量的指针变量的阐明是相反的。

  引入指针变量后, 就可以用两种方法来拜访数组元素了。

  第一种方法为下标法, 即用a形式拜访数组元素。 在第四章中介绍数组时都是采用这种方法。

  第二种方法为指针法, 即采用形式, 用间接拜访的方法来拜访数组元素。

  main

  pa=a;

  for

  ??br/>
  主函数

  定义整型数组和指针

  将指针pa指向数组a

  循环

  将变量i的值赋给由指针pa指向的a的数组单元

  将指针pa指向a的下一个单元

  。 。 。 。 。 。

  指针pa重新取得数组a的首地址

  循环

  用数组方式输出数组a中的所有元素

  将指针pa指向a的下一个单元

  。 。 。 。 。 。

  。 。 。 。 。 。

  下面, 另举一例, 该例与上例本意相反, 但是实现方式不同。

  main

  ??br/>
  主函数

  定义整型数组和指针, 并使指针指向数组a

  循环

  将变量i的值赋给由指针pa指向的a的数组单元

  用指针输出数组a中的所有元素, 同时指针pa指向a的下一个单元

  。 。 。 。 。 。

  。 。 。 。 。 。

  数组名和数组指针变量作函数参数

  在第五章中曾经介绍过用数组名作函数的实参和形参的效果。 在学习指针变量之后就更容易了解这个效果了。 数组名就是数组的首地址, 实参向形参传送数组名实际上就是传送数组的地址, 形参得到该地址后也指向同一数组。 这就好象同一件物品有两个彼此不同的名称一样。 异样, 指针变量的值也是地址, 数组指针变量的值即为数组的首地址, 当然也可作为函数的参数使用。

  floataver;

  main

  floataver

  指向多维数组的指针变量

  本大节以二维数组为例介绍多维数组的指针变量。

  一、多维数组地址的表示方法

  设有整型二维数组a如下:

  023

  4567

  891011

  设数组a的首地址为1000, 各下标变量的首地址及其值如所示。 在第四章中介绍过, c言语允许把一个二维数组分解为多个一维数组来处置。 因此数组a可分解为三个一维数组, 即a, a, a。 每一个一维数组又含有四个元素。 例如a数组, 含有a, a, a, a四个元素。 数组及数组元素的地址表示如下:a是二维数组名, 也是二维数组0行的首地址, 等于1000。 a是第一个一维数组的数组名和首地址, 因此也为1000。 或a是与a等效的, 它表示一维数组a0号元素的首地址。 也为1000。 a是二维数组a的0行0列元素首地址, 异样是1000。 因此, a, a, , a, a是相等的。 同理, a+1是二维数组1行的首地址, 等于1008。 a是第二个一维数组的数组名和首地址, 因此也为1008。 a是二维数组a的1行0列元素地址, 也是1008。 因此a+1, a, , a是等同的。 由此可得出:a+i, a, , a是等同的。 此外, a和a也是等同的。 因为在二维数组中不能把a了解为元素a的地址, 不存在元素a。

  ?阊杂锕嬖颍?它是一种地址计算方法, 表示数组a第i行首地址。 由此, 我们得出:a, a, 和a+i也都是等同的。 另外, a也

  可以看成是a+0是一维数组a的0号元素的首地址, 而a+1则是a的1号元素首地址, 由此可得出a+j则是一维数组a的j号元素首地址, 它等于a。 由a=得a+j=+j, 由于+j是二维数组a的i行j列元素的首地址。 该元素的值等于+j)。

  printf;

  printf, a, a, a);

  printf, a, a, a);

  printf+1);

  printf, +1));

  ??br/>
  二、多维数组的指针变量

  把二维数组a分解为一维数组a, a, a之后, 设p为指向二维数组的指针变量。 可定义int它表示p是一个指针变量, 它指向二维数组a或指向第一个一维数组a, 其值等于a, a, 或a等。 而p+i则指向一维数组a。 从前面的剖析可得出+j是二维数组i行j列的元素的地址, 而+j)则是i行j列元素的值。

  二维数组指针变量阐明的普通形式类型阐明符其中“类型阐明符”为所指数组的数据类型。 “”表示其后的变量是指针类型。 “长度”表示二维数组分解为多个一维数组时, 一维数组的长度, 也就是二维数组的列数。 应留意“”两边的括号不可少, 如缺少括号则表示是指针数组, 意义就完全不同了。

  main;

  int;

  inti, j;

  p=a;

  for

  forprintf+j));

  ??br/>
  ’expain字符串指针变量的阐明和使用字符串指针变量的定义阐明与指向字符变量的指针变量阐明是相反的。 只能按对指针变量的赋值不同来区别。 对指向字符变量的指针变量应赋予该字符变量的地址。 如:charc, p=c;表示p是一个指向字符变量c的指针变量。 而:chars=“clanguage“;则表示s是一个指向字符串的指针变量。 把字符串的首地址赋予s。

  请看下面一例。

  main

  运行后果

  clanguage

  上例中, 首先定义ps是一个字符指针变量, 然后把字符串的首地址赋予ps, 并把首地址送入ps。 顺序中的:charps;ps=“clanguage“;等效于:charps=“clanguage“;输出字符串中n个字符后的所有字符。

  main

  运行后果

  book在顺序中对ps初始化时, 即把字符串首地址赋予ps, 当ps=ps+10之后, ps指向字符“b”, 因此输出为“book“。

  main

  ifprintf;

  ??br/>
  本例是在输入的字符串中查找有无‘k’字符。 下面这个例子是将指针变量指向一个格式字符串, 用在printf函数中, 用于输出二维数组的各种地址表示的值。 但在printf语句中用指针变量pf替代了格式串。 这也是顺序中常用的方法。

  main;

  charpf;

  pf=“%d, %d, %d, %d, %d\n“;

  printf;

  printf, a, a, a);

  printf, a, a, a);

  printf+1);

  printf, +1));

  ??br/>
  在下例是讲解, 把字符串指针作为函数参数的使用。 要求把一个字符串的内容复制到另一个字符串中, 并且不能使用strcpy函数。 函数cprstr的形参为两个字符指针变量。 pss指向源字符串, pds指向目的字符串。 表达式:

  ?。 絗\0’

  cpystr

  ??br/>
  main

  在上例中, 顺序完成了两项任务:一是把pss指向的源字符复制到pds所指向的目的字符中, 二是判断所复制的字符是否为`\0’, 若是则标明源字符串结束, 不再循环。 否则, pds和pss都加1, 指向下一字符。 在主函数中, 以指针变量pa, pb为实参, 分别取得确定值后调用cprstr函数。 由于采用的指针变量pa和pss, pb和pds均指向同一字符串, 因此在主函数和cprstr函数中均可使用这些字符串。 也可以把cprstr函数简化为以下形式:

  cprstr

  即把指针的移动和赋值兼并在一个语句中。 进一步剖析还可发现`\0’的ascⅱ码为0, 对于while语句只看表达式的值为非0就循环, 为0则结束循环, 因此也可省去“!?絗\0’”这一判断部分, 而写为以下形式:

  cprstr

  表达式的意义可解释为, 源字符向目的字符赋值, 移动指针, 若所赋值为非0则循环, 否则结束循环。 这样使顺序更加繁复。 简化后的顺序如下所示。

  cpystr

  main

  使用字符串指针变量与字符数组的区别

  用字符数组和字符指针变量都可实现字符串的存储和运算。 但是两者是有区别的。 在使用时应留意以下几个效果:

  1。 字符串指针变量本身是一个变量, 用于寄存字符串的首地址。 而字符串本身是寄存在以该首地址为首的一块延续的内存空间中并以‘\0’作为串的结束。 字符数组是由于若干个数组元素组成的, 它可用来寄存整个字符串。

  2。 对字符数组作初始化赋值, 必须采用外部类型或静态类型, 如:staticcharst=;而对字符串指针变量则无此限制, 如:charps=“clanguage“;

  3。 对字符串指针方式charps=“clanguage“;可以写charps;ps=“clanguage“;而对数组方式:

  staticcharst=;

  不能写

  charst;st=;

  而只能对字符数组的各元素逐个赋值。

  从以上几点可以看出字符串指针变量与字符数组在使用时的区别, 同时也可看出使用指针变量更加方便。 前面说过, 当一个指针变量在未取得确定地址前使用是危险的, 容易引起错误。 但是对指针变量直接赋值是可以的。 因为c系统对指针变量赋值时要给以确定的地址。 因此,

  charps=“clangage“;

  或者charps;

  ps=“clanguage“;都是合法的。

  函数指针变量

  在c言语中规则, 一个函数总是占用一段延续的内存区, 而函数名就是该函数所占内存区的首地址。 我们可以把函数的这个首地址赋予一个指针变量, 使该指针变量指向该函数。 然后经过指针变量就可以找到并调用这个函数。 我们把这种指向函数的指针变量称为“函数指针变量”。

  函数指针变量定义的普通形式

  类型阐明符;

  其中“类型阐明符”表示被指函数的返回值的类型。 “”表示“”前面的变量是定义的指针变量。 最后的空括号表示指针变量所指的是一个函数。

  例如:int;

  表示pf是一个指向函数入口的指针变量, 该函数的返回值是整型。

  下面经过例子来阐明用指针形式实现对函数调用的方法。

  intmax

  main

  从上述顺序可以看出用, 函数指针变量形式调用函数的步骤如下:1。 先定义函数指针变量, 如后一顺序中第9行int;定义pmax为函数指针变量。

  2。 把被调函数的入口地址赋予该函数指针变量, 如顺序中第11行pmax=max;

  3。 用函数指针变量形式调用函数, 如顺序第14行z=;调用函数的普通形式使用函数指针变量还应留意以下两点:

  a。 函数指针变量不能停止算术运算, 这是与数组指针变量不同的。 数组指针变量加减一个整数可使指针移动指向前面或前面的数组元素, 而函数指针的移动是毫有意义的。

  b。 函数调用中““的两边的括号不可少, 其中的不应该了解为求值运算, 在此处它只是一种表示符号。

  指针型函数

  前面我们介绍过, 所谓函数类型是指函数返回值的类型。 在c言语中允许一个函数的返回值是一个指针, 这种返回指针值的函数称为指针型函数。

  定义指针型函数的普通形式

  类型阐明符函数名

  其中函数名之前加了“”号标明这是一个指针型函数, 即返回值是一个指针。 类型阐明符表示了返回的指针值所指向的数据类型。

  如:

  intap

  表示ap是一个返回指针值的指针型函数, 它返回的指针指向一个整型变量。 下例中定义了一个指针型函数day_name, 它的返回值指向一个字符串。 该函数中定义了一个静态指针数组name。 name数组初始化赋值为八个字符串, 分别表示各个星期名及出错提示。 形参n表示与星期名所对应的整数。 在主函数中, 把输入的整数i作为实参, 在printf语句中调用day_name函数并把i值传送给形参n。 day_name函数中的return语句包括一个条件表达式, n值若大于7或小于1则把name指针返回主函数输出出错提示字符串“illegalday”。 否则返回主函数输出对应的星期名。 主函数中的第7行是个条件语句, 其语义是, 如输入为负数则中止顺序运行参与顺序。 exit是一个库函数, exit表示发生错误后参与顺序, exit表示正常参与。

  应该特别留意的是函数指针变量和指针型函数这两者在写法和意义上的区别。 如int和intp是两个完全不同的量。 int是一个变量阐明, 阐明p是一个指向函数入口的指针变量, 该函数的返回值是整型量, 的两边的括号不能少。 intp则不是变量阐明而是函数阐明, 阐明p是一个指针型函数, 其返回值是一个指向整型量的指针, p两边没有括号。 作为函数阐明, 在括号内最好写入形式参数, 这样便于与变量阐明区别。 对于指针型函数定义, intp只是函数头部分, 普通还应该有函数体部分。

  main

  C++charday_name;

  return?name:name);

  ??br/>
  本顺序是经过指针函数, 输入一个1~7之间的整数, 输出对应的星期名。 指针数组的阐明与使用一个数组的元素值为指针则是指针数组。 指针数组是一组有序的指针的集合。 指针数组的所有元素都必须是具有相反存储类型和指向相反数据类型的指针变量。

  指针数组阐明的普通形式类型阐明符数组名

  其中类型阐明符为指针值所指向的变量的类型。 例如:intpa表示pa是一个指针数组, 它有三个数组元素, 每个元素值都是一个指针, 指向整型变量。 通常可用一个指针数组来指向一个二维数组。 指针数组中的每个元素被赋予二维数组每一行的首地址, 因此也可了解为指向一个一维数组。 6—6表示了这种关系。

  inta=;

  intpa=;

  intp=a;

  main

  本例顺序中, pa是一个指针数组, 三个元素分别指向二维数组a的各行。 然后用循环语句输出指定的数组元素。 其中a表示i行0列元素值;+i)表示i行i列的元素值;pa表示i行0列元素值;由于p与a相反, 故p表示0行i列的值;表示0行i列的值。 读者可仔细领会元素值的各种不同的表示方法。 应该留意指针数组和二维数组指针变量的区别。 这两者虽然都可用来表示二维数组, 但是其表示方法和意义是不同的。
文章由左旋肉碱整理,收集辛苦,希望能保留出处。

posted on 2011-05-30 23:22  jiyizhen3721  阅读(301)  评论(0编辑  收藏  举报