写在前面
一个偶然的机会,学校ACM协会举行了一次试讲活动,内容为大一的C语言。而我恰巧分到了我最怕的、也是最难的指针,几经周折,多方请教,受益颇多。
此处整理出来,若能对读者有些许感触,也是极好的
一、内存中的数据是怎么存储的
内存中数据的存储如下:
   线性,顺序,并且  “每个” 内存空间都有与之对应的地址
举个例子吧
      如果将内存比作一个宾馆,将每一个存储空间比作一个房间,那么内存地址就相当于门牌号
二、程序中常用的“寻址方式”
此处只是列举的三个常用的,因为重点不在这里
(1)立即寻址
  指令的地址字段指出的不是操作数的地址,而是操作数本身
(2)直接寻址
在指令格式的地址的字段中直接指出操作数在内存的地址
(3)间接寻址
 间接寻址是相对直接寻址而言的,
在间接寻址的情况下,指令地址字段中的形式地址不是操作数的真正地址,
而是操作数地址的指示器,或者说此形式地址单元的内容才是操作数的有效地址。
比如
int b=0, a=3+2;//0,2和3属于立即寻址,也就是需要用的数据本身就在程序里面  
int c=a+b;//此处根据a和b的名字来操作数据,a和b的其实可以用地址来替换,只不过写上一个0x***的没有只写上一个a简单,方便  
int *p=&c //此处的p就是间接寻址,p中存储的不是数据而是数据的地址  
三、指针是什么?
在理解了内存中的数据的存储方式已经常用的寻址方式后,再来谈指针就会轻松许多。
     指针其实就是一个记录数据的地址的变量,
      
      换言之,指针也是变量,只不过其中存储的不是数据而是地址。
如果你明白了什么是指针的话,那么多级指针之类的,都很容易理解.
拿二级指针来举例
    二级指针就是指向指针的指针,两个指针里面存储的都是地址,
    
    一级指针里面存储的是变量的地址,二级指针里面存储的是指针的地址
那么问题来了
既然指针中存储的是地址,内存中地址的长度(最大值)是确定的,那么为什么还要将指针分类为指向整形的,指向字符型等等???????
拿指向数组的指针来说吧
 在操作指向数组的指针时,肯定会牵扯到指针的自增,
  
  此时系统就是根据指针类型的不同来判断自增的内存地址的多少
  
 (一个整形占4个字节,那么就一次增加4个单元格,一个字符占一个字节,那么一次就增加一个字节)
四、指针能做什么
很多人(cai niao)都说,不用指针,我一样可以完成很多事情,为什么非要用指针,指针能做什么???
1 .什么时候用指针
如果用一个指针去指向一个变量的话,意义不大(自我感觉),在我看来(不一定正确)最常用的地方有两个
①用指针指向一个数组
例子一枚
#include<stdio.h>  
void main(){  
    int arr[]={1,2,3,5,31};  
    int *p=arr;  
    printf("%d\n",*(p+1));  
    printf("%d\n",*(arr+1));  
    printf("%d\n",arr[1]);  
    printf("%d\n",p[1]);  
    printf("-----------\n");  
    printf("%o\n",p);  
    printf("%o\n",arr);  
    printf("%o\n",&arr);  
    printf("%o\n",&arr[0]);  
}  
②用指针指向一个结构体
只要知道
      结构体的指针来获取内部属性用的是“->”
2.为什么用指针
   在我看来,在一般情况下不用指针也可以完成程序所需要的功能,
    用指针是为了提高程序的效率,对程序进行优化
拿数组来举个例子。
选择排序
/例一、函数传递的是数组/
#include<stdio.h>  
void main(){  
    void swap(int arr[],int x,int y);  
    void sort1(int arr[],int n);  
    void printfArr(int arr[],int n);  
    int arr[]={111,22,13,4,51};  
    sort1(arr,5);  
    printfArr(arr,5);  
}  
void swap(int arr[],int x,int y){  
    int temp=arr[x];  
    arr[x]=arr[y];  
    arr[y]=temp;  
}  
void sort1(int arr[],int n){  
int i=0,j=0,max=0;  
    for(i=0;i<n-1;i++){  
        max=i;  
        for(j=i+1;j<n;j++){  
            if(arr[j]>arr[max]){  
                max=j;  
            }  
        }  
        swap(arr,max,i);  
    }  
}  
void printfArr(int arr[],int n){  
    int i=0;  
    for(i=0;i<n;i++){  
        printf("%d\n",arr[i]);  
    }  
}  
/例二、函数传递的是指针/
#include<stdio.h>  
void main(){  
    void swap(int *p,int x,int y);  
    void sort2(int *p,int n);  
    void printfArr(int *p,int n);  
    int arr[]={111,22,13,4,51};  
    int *p=arr;  
    sort2(p,5);  
    printfArr(p,5);  
}  
void swap(int *p,int x,int y){  
    int temp=p[x];  
    p[x]=p[y];  
    p[y]=temp;  
}  
  
void sort2(int *p,int n){  
int i=0,j=0,max=0;  
    for(i=0;i<n-1;i++){  
        max=i;  
        for(j=i+1;j<n;j++){  
            if(p[j]>p[max]){  
                max=j;  
            }  
        }  
        swap(p,max,i);  
    }  
  
}  
void printfArr(int*p,int n){  
    int i=0;  
    for(i=0;i<n;i++){  
        printf("%d\n",p[i]);  
    }  
}  
虽然结果都是能够对数组进行排序然后输出,但是其效率是完全不一样的。
为什么效率会不同呢???
- 
如果参数传递的是一个数组,
函数在接收参数时会对数组进行一次复制(或者说将整个数组取出来),消耗较大,
有时候可能不一定用到数组中的所有的元素(比如例子中的swap函数) 如果传递的是指针的话,
好的一方面是仅仅传递一个指针,比较小,速度快;
但需要用到整个数组中的元素时,又需要根据指针多长访问内存,时间耗时在了此处。