一、指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型、指针所指向的类型、指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。
  1.指针的类型
  从语法角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分是这个指针的类型。例如:int *ptr;//指针类型是int*;int**ptr;//指针类型是int**
  2.指针所指向的类型
  从语法上看,你只需把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的是指针所指向的类型。例如:int *ptr;//指针所指向的类型是int;int**ptr;//指针所指向的类型是int*;
  3.指针的值--或者叫指针所指向的内存区或地址
  指针的值是指针本身存储的数值,这个值将被编译器当做一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数。因为32位程序里内存地址全都是32位长。
  4.指针本身所占据的内存区
  在32位平台里,指针本身占据了4个字节的长度。
  二、指针可以加上或减去一个整数,指针的这种运算的意义与通常数值的加减意义不同,是以单元为单位的。
  三、当一个指针表达式的结果指针已经明确具有了指针内身占据的内存的话,这个表达式是一个左值。
  四、例子:
  char *str[3]={
  "Hello,this is a sample!",
  "Hi,good morning",
  "Hello,world"
  };
  上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当做一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char*。
  *str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串“Hello,this is a sample!”的第一个字符的地址,即H的地址。注意:字符串相当于是一个数组,在内存中以数组的形式储存,只不过字符串是一个数组常量,内容不可改变,且只能是右值。如果看成指针的话,它既是常量指针,也是指针常量。
  str+1也是一个指针,它指向数组的第一号单元,它的类型是char**,它指向的类型是char*。
  *(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向“Hi,good morning。”的第一个字符H。
  下面总结下数组的数组名的问题:
  声明一个数组TYPE array[n],则数组名称array有了两重含义:
  第一:它代表整个数组,它的类型是TYPE[n];第二:它是一个常量指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也是数组单元的类型,该指针指向的内存区是是数组第0号单元,该指针自己站有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。
  五、指针和结构类型的关系
  例:
  struct MyStruct
  {
  int a;
  int b;
  int c;
  };
  struct MyStruct ss={20,30,40}; //声明了结构对象ss,并把ss的成员初始化为20,30,40.
  struct MyStruct *ptr=&ss; //声明了一个指向结构对象ss的指针。它的类型是MyStruct
  int *pstr=(int *)&ss; //声明了一个指向结构对象ss的指针。但是pstr和它被指向的类型ptr是不同的。
  请问怎样通过指针ptr来访问ss的三个成员变量?
  答案:
  ptr->a; //指向运算符,或者(*ptr).a
  ptr->b;
  ptr->c;
  又请问怎样通过指针pstr来访问ss的三个成员变量?
  答案:
  *pstr; //访问ss的成员a
  *(pstr+1); //访问ss的成员b
  *(pstr+2); //访问ss的成员c
  实际中,所有的C/C++编译器在排列数组的单元是,总是把各个数组单元存放在连续的存储区里面,单元和单元之间没有空隙。但在存放结构对象的各个成员是,在某种编译环境下可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个“填充字节”,这导致各个成员之间可能会有若干个字节的间隙。
  六、指针和函数的关系
  可以吧一个指针声明为一个指向函数的指针。
  int fun1(char *,int);
  int (*pfun1)(char *,int);
  pfun1=fun1;
  int a=(*pfun1)("abcdefg",7); //通过函数指针调用函数。可以把指针作为函数的形参,在函数调用语句中,可以用指针表达式来作为实参。
  七、指针的安全问题
  例:
  char s='a';
  int *ptr;
  ptr=(int *)&s;
  *ptr=1298;
  指针ptr是一个int *类型的指针,它指向的类型是int。它指向的地址是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。后一条语句不但改变了s所占的一个字节,还把和s相邻的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人不太可能知道。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。
  所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。
  在指针强制类型转换:ptr1=(TYPE *)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。