1.何为指针:
  程序运行时,任何变量都是存放在内存中的,通过将内存以字节的大小划分,为每个字节增添索引,某一变量的地址就是该变量在内存中所占的第一个字节的索引。此时,定义一变量用来存放开始第一个字节的索引,这个变量就被称为指针,通过该变量的值可以间接的访问该指针所指向的变量。在32位系统中,指针的大小都是4字节,可以索引最大4G的内存。

  2.指针定义  

int a = 10;int *p = &a;int b[3] = {1,2,4};int *p = b;

 3.常见指针类型的识别 

// *的优先级最低,当类型比较复杂时,一步一步的进行分析,还可以将某一部分看作整体进行简化分析int        p;int        *p;                // p与*结合,说明p是一个指针,再与int结合,说明p是一个指向int的指针int        p[3];            // p与[]结合,说明P是数组,再与int结合,说明p是一个存放int变量的数组int        *p[3];            // p与[]结合,说明p是一个数组,再与*结合,说明数组中存放的是指针,指针类型是int,说明p是一个指向存放int型指针数组的指针int        (*p)[3];        // p与*结合,说明p是指针,再与[]结合,说明p指向一个数组,该数组里存放intint        **p;            // p是一个只想int指针的指针int        p(int);            // p是一个函数,该函数参数为int,返回类型为intint        (*p)(int);        // p是一个指针,该指针指向一个函数,函数参数为int,返回类型为intint   *(*p(int))[3];    // p是一个函数,该函数参数为int,返回类型为一个指针,该返回类型的指针指向一个数组,次数组中存放的是int的指针

4.指针基本概念
    指针的类型:把指针名去掉后的类型就是指针的类型,比如int prt的类型就是int  
    指针指向的类型:去掉指针名和*之后的类型,比如int *prt指向的类型就是int。
    指针的值:指针所指向的内存,也是指针变量所在内存中存放的值,在32位系统中指针是一个32位的变量,该值被当作一个地址,而不是简单的字面值
    指针的地址:指针本身在内存中的地址,该地址是不可改变的

  5.指针运算
    指针可以加上或减去一个整数,计算时,以指针所指向的类型大小为单位。
例如: 

typeA *ptr;unsigned int addrA = (usigned int)ptr;unsigned int addrB = (usigned int)(ptr + 1);unsigned int ret = addrB - addrA;

则ret的大小实际是sizeof(typeA)的大小,也就是ptr +1时,编辑器在ptr所指向内存的地方往后移动了sizeof(typeA)个字节。
分析以下打印的结果:

char a[20] = " You_are_a_girl";char *p = a;char **ptr = &p;printf("**ptr=%c\n", **ptr);// Yptr++;printf("**ptr=%c\n", **ptr);// 未定义

ptr为二级指针,*ptr等同于p,p指向a[0],则**ptr = ‘Y’
ptr为二级指针,ptr指向p,也就是ptr存放的是p的地址,对ptr自增,相当于&p + sizeof(char ),并不指向a中的任何数据,行为未定义

  6.指针表达式
  如果一个表达式的结果是一个指针,则这个表达式称为指针表达式。 
例:  

char *str[3] = {    "Hello,thisisasample!",    "Hi,goodmorning.",    "Helloworld"}; 
chars[80];
strcpy(s, str[0]); //也可写成 strcpy(s,*str);strcpy(s, str[1]); //也可写成 strcpy(s,*(str+1));

指针类型转换:
  不同的指针之间可以强制转换,也可以将整形当作一个地址强制转换为某一类型的指针。类型强制转换时需要保证源指针指向的类型所占字节不比转换后的类型小,否则可能造成越界。  

struct st_type {    int a;    int b;    int c;
};struct st_type st = { 5,4,3 };struct st_type *stptr = &st;int *p = (int *)stptr;
(*p) = 1;    // 给a重新赋值*(p + 1) = 3;  // 给b重新赋值*(p + 2) = 5;  // 给c重新赋值

在使用时,可能会由于字节对齐的原因导致通过上述方式存取是发生错误,使用前必须人为指定字节对齐的大小,比如:

#pragma pack(push) //保存对齐状态#pragma pack(4)//设定为4字节对齐struct st_aaaa{    int a;    int b;    char c;    long d;  
};#pragma pack(pop)//恢复对齐状态