指针专题2

来自http://community.csdn.net/Expert/topic/3172/3172383.xml?temp=.1944544

 

其实并没有所谓的“指针类型”,而只有指针所指对象的类型。换言之,指针只是保存对象地址的一个容器而已,强加于其上的对象类型只是一种编译期信息,用于提示编译器该从此地址取出多少个字节来交差罢了。所以不能把指针所指对象的类型和指针本身的类型切开来看,而是从一开始就应该把它们当成一回事。可以说,类型系统中有多少种类型,就应该有多少种指针(同样地,就可以有多少种引用,多少种数组,多少种……:)。噢噢,话归正题,下面一一为大家讲解指针的类型,顺便提醒一下在针指使用过程中容易出错的地方。

  (PS:刚才废人说《TCPL》把指针看作是别的类型的“派生类型”,很值得玩味。)

  1、最简单的指针:指向单一对象的指针(为什么我是说“对象”而非“变量”呢?因为对象才是类型系统要处理的东东,变量只是对象的实现手法)。示例如下:

  int *pi;   // 声明+定义一个指向int类型对象的指针

  以上语句在只是简单地声明+定义了一个指针,在符号表中引入了指针的名字,同时保存了类型信息。但是这样的写法有可能会被报警,因为C编译器大多会针对未进行初始化的指针扔出一个警告(警告粗心大意的程序员,直接定义的局部变量未经初始化时的值是随机的,而对一个拥有随机地址的指针进行对象引用……Bombing!)。所以我们最好这样写:

  int a, *pi = &a; 或者 int *pi = NULL;  // 国内的C相关考试最喜欢在这里出考题

  记得一点,定义一个指针就要对它初始化,没错的。而引用所指对象也很简单,*pi就是了。概念上可以把*pi当做a来用,但要注意运算符的优先级(比如*p++和*(p++)还有*++p……头疼了吧?:)。

  2、比较复杂的指针:指向复合对象的指针。复合对象可能是数据的聚合(比如数组,结构体,枚举),也可能是类型的聚合(比如联合体),换言之,复合对象是“用户定义类型”,千变万化类型各异。但不管它们怎么变,总会有对应的指针指向它们的实例对象(书上说指针是其它类型的派生类型,越想越有道理)。示例一:

  struct HUMAN {
    char name[24];
    int age;
  }h;
  struct HUMAN *ph = &h;

  要通过指针引用结构体的成员,可以使用->操作符,比如ph->name[0]或者ph->age。同样地,*ph在概念上与h等价,可以这样使用*ph.age(有时候加上一对括号比较安全,(*ph).age)。

  示例二:
  union MSG_ENTRY {
    int (*Button_Click)(POINT *pp);
    void (*Idle)(void);
  }me;
  union MSG_ENTRY * pm = & me;

  要通过指针引用联合体的成员,同样可以使用->操作符,比如pm->Button_Click或者pm->Idle。而*pm也与me等价。但提请注意,pm->Button_Click与pm->Idle两者的地址实际上是一样的。这是联合体与结构体的基本差异所在。

  示例三:
  typedef int ARRAY[10];
  ARRAY a;
  ARRAY * pa = & a;

  在这里,pa所指对象(即a对象)的类型可能会令人迷惑。但仔细观察分析后就可以知道,a的类型是一个拥有10个整型元素的数组,而pa就是指向此对象的指针。也就是说,pa的类型应该是int (*)[10]。请大家注意(*)和[10],前者是将指针限定为“指向数组”,后者则限定了“该数组的大小”。如有以下代码:
  int b[5];
  pa = &b;  // 编译器应当报警,因为int [5]类型无法与int (*)[10]兼容

  嘿嘿……看明白了?也就是说,数组大小也成为限定饰修的一部分。

  还有几个非常容易混淆的类型是:
  int *p[10];
  int (*pp)[10];
  int *(*ppp)[10];

  其中,p是一个数组,拥有10个int *类型的元素。而pp是一个指针,指向int [10]类型的数组对象。ppp也是一个指针,指向int *[10]类型的数组对象。所以可以这样写:
  ppp = &p;  // ok
  却不能这样写:
  pp = &p;  // 两者的类型无法兼容

  (PS:有关数组与指针的关系,可以参考我写的另外一篇小专题,URL为http://community.csdn.net/Expert/topic/3142/3142075.xml?temp=.2214624。而且数组与指针的关系还可以扩展来讲,这是后话,按下不表)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值