浅谈指针

写在前面

一个偶然的机会,学校ACM协会举行了一次试讲活动,内容为大一的C语言。而我恰巧分到了我最怕的、也是最难的指针,几经周折,多方请教,受益颇多。

此处整理出来,若能对读者有些许感触,也是极好的


一、内存中的数据是怎么存储的

内存中数据的存储如下:

浅谈指针_第1张图片
   线性,顺序,并且  “每个” 内存空间都有与之对应的地址

举个例子吧

      如果将内存比作一个宾馆,将每一个存储空间比作一个房间,那么内存地址就相当于门牌号

二、程序中常用的“寻址方式”

此处只是列举的三个常用的,因为重点不在这里

(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  
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张图片

②用指针指向一个结构体

只要知道

      结构体的指针来获取内部属性用的是“->”

2.为什么用指针

   在我看来,在一般情况下不用指针也可以完成程序所需要的功能,

    用指针是为了提高程序的效率,对程序进行优化

拿数组来举个例子。

选择排序

/例一、函数传递的是数组/

#include  
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;iarr[max]){  
                max=j;  
            }  
        }  
        swap(arr,max,i);  
    }  
}  
void printfArr(int arr[],int n){  
    int i=0;  
    for(i=0;i

/例二、函数传递的是指针/

#include  
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;ip[max]){  
                max=j;  
            }  
        }  
        swap(p,max,i);  
    }  
  
}  
void printfArr(int*p,int n){  
    int i=0;  
    for(i=0;i
浅谈指针_第3张图片

虽然结果都是能够对数组进行排序然后输出,但是其效率是完全不一样的。


为什么效率会不同呢???

  • 如果参数传递的是一个数组,

    函数在接收参数时会对数组进行一次复制(或者说将整个数组取出来),消耗较大,
    有时候可能不一定用到数组中的所有的元素(比如例子中的swap函数)

  • 如果传递的是指针的话,
    好的一方面是仅仅传递一个指针,比较小,速度快;
    但需要用到整个数组中的元素时,又需要根据指针多长访问内存,时间耗时在了此处。

因此,具体怎么取舍,还是要看具体情况


你可能感兴趣的:(浅谈指针)