指针和数组总结

来源:互联网 发布:骑马与砍杀捏脸数据男 编辑:程序博客网 时间:2024/05/20 16:18

    • 指针
      • 什么是指针
      • 指针类型
      • 解引用指针
      • 指针运算
      • 二级指针
      • 使用指针注意事项
    • 数组
      • 一维数组
      • 二维数组
    • 指针和数组
      • 数组指针
      • 指针数组
      • 指针和数组的区别
    • 函数丶指针和数组
      • 函数指针
      • 函数指针数组
      • 函数指针数组指针

指针

什么是指针

计算机内存中每个位置都有个独一无二的地址,每个地址上都存储着一个值,如果你记住了一个值的地址,就可以根据这个地址来访问地址上的值,但地址通常都用一串很长的号码来表示,这显然给我们的编程带来了诸多不便,因此我们应该给所知道的地址取一个温暖的名字,这些名字就被统称为指针变量。

指针类型

每个地址上存储的值的而类型都不尽相同,因此,为了操作的方便,指针也分为不同类型

int n;char c;int* pn = &n;   //将n的地址保存在int*类型的指针pn中char* pc = &c;  //将c的地址保存在char*类型的指针pc中//...

解引用指针

通过一个指针访问它所指向地址的内容,这个过程我们叫做解引用指针,用操作符*来完成。

int main(){    int n = 6;    int* pn = &n;    printf("*pn=%d",*pn);   //通过解引用pn,访问到n地址处的内容    *pn = 233;      //通过指针改变n地址处的内容    printf("n=%d",n);     return 0;}

这里写图片描述

指针运算

  • 给指针加(减)1,指针向前(向后)移动的距离是由指针类型决定的。
    例如 :给char*类型的指针加1,指针将指向原来位置的下一个字节处;
    给int*类型的指针加1,指针将指向原来位置的下四个字节处。
  • 两个同类型指针相减,得到的值是以这个指针类型大小为单位分割的内存块的个数。

二级指针

二级指针即指针的指针,如果我们想访问指针的地址,就必须通过二级指针来访问。

    int n = 6;    int *pn = &n;    int **ppn = &pn;//ppn为二级指针

可以通过**ppn找到n的值

使用指针注意事项

  • 禁止使用未被初始化的指针。
    例如:
int* n;*n = 6;

上面这段代码是不被允许的,因为我们没有对指针变量n进行初始化,我们无法预测n指向了那块内存,对里面的值进行访问和更改,是一件很危险的事情。所以,一定要对指针进行初始化。

  • 对指针赋值时一定要保证类型匹配,否则在操作指针是会访问不到原来的值。

  • 声明指针时不能连续声明多个,例如int* a,b;它表达的意思是声明了一个int*类型的a,和一个int类型的b。

  • 不能对NULL指针进行解引用。

数组

一维数组

数组表示一些相同类型的值的集合。例如,int a[5]表示一个数组里面有5个int类型的数据。其中a[0]表示第一个元素,a[4]表示最后一个元素。
数组名数字名是一个指针常量,它表示数组首元素的地址,它的类型取决于数组元素的类型。数组名放到sizeof内部时,返回的是整个数组的大小(20)而不是指针的大小。
那么,*(a+1)表示什么意思呢?
首先,a是一个指向整型的指针,所以加1加的是一个整型的长度,a表示的是第一个元素的地址,所以a+1表示的是第二个元素的地址,*(a+1)当然就是数组a的第二个元素了。对于这种表示方法,它比a[1]的效率更高 ,因为本质上编译器是把a[1]转化成*(a+1)来执行的。

二维数组

数组还可以用多维表示,我们以二维数组为例int a[3][4],我们可以认为这是一个三行四列的整型二维数组。但是,二维数组在内存的存储是连续的

这里写图片描述

那么,*(*(a+1)+2)表示什么意思呢?
在数组中,数组名表示数组首元素的地址,二维数组首元素其实是指第一行,所以给a加1跳过的是一整行,*(a+1)相当于的二行的数组名,给第二行的数组名加2表示第二行的第3个元素的地址,所以整个表达式式第二行第3个元素,相当于a[1][2]。

指针和数组

数组指针

当我们想让一个指针指向一个数组时,应该这样声明:int (*p)[5];
此时 ,p是一个数组指针,它指向一个数组,数组有5个元素,每个元素为int类型。

指针数组

当我们想让一个数组保存的类型为指针时,应该这样声明:int *p[5];
此时,p是一个数组,素组有5个元素,每个元素为int*类型。

指针和数组的区别

很多时候,我们可以把指针当成数组,把数组中当成指针。但是,指针和数组不是完全相同的,下面用指针和数组的定义和声明来说明问题。

  • 定义为数组,声明为指针
    这里写图片描述
    我们在文件1.c定义了一个数组a,我们试图以一个指针的形式声明数组a,然后输出数组的大小,下面是运行结果:
    这里写图片描述
    结果让人很意外,按道理整个数组的大小应该是20个字节,说明在2.c里编译器根本就没把a当成数组,而是当成一个指针,如果这里把a当成一个数组进行操作,显然是不合理的。

  • 定义为指针,声明为数组
    这里写图片描述
    同样的,我们在1.c里面定义一个字符串指针,然后在2.c里面声明成一个数组,我们天真的以为2.c的p里面保存的是”10086”的地址,然后很嗨皮的对它进行访问,结果如下:
    这里写图片描述
    结果又不尽人意,too naive!你以为你以为的就是正确的,可是编译器不这么认为,在2.c里面,编译器认为p是一个数组,它指向了另一块空间。

指针和数组的其它区别:

注:下面表格摘自《c专家编程》

指针 数组 保存数据的地址 保存数据 间接访问数据,首先取得指针内容,把它作为地址,
然后从这个地址提取数据。
如果指针有一个下标[i],就把指针的内容加上i作为地址
从中提取内容 直接访问数据 通常用于动态数据结构 通常用于存储固定数目且数据类型相同的元素 相关的函数为malloc(),free() 隐式分配和删除 通常指向匿名数据 自身即为数据名

函数丶指针和数组

函数指针

可以把一个指针声明为指向函数的指针
例如: void (*pfun)();
pfun就是一个函数指针,它有能力指向一个函数,比如说我们有一个简单的函数

void print(){    printf("苟利国家生死以,岂因祸福避趋之。\n");}

然后让pfun指向这个函数

pfun = print;//函数名就是函数的地址

我们可以通过函数指针来调用这个函数

int main(){    pfun();    return 0;}

这里写图片描述

其实 ,函数指针真正的用途是,当我们想给函数a里面传递另一个函数b时,我们可以通过传递一个指向函数b的函数指针作为函数a的参数来传递,这个过程被称作回调函数

函数指针数组

一个数组,数组元素了函数指针类型
例如void (*pfunarr[])();

函数指针数组指针

例如void (*(*pfunarr[]))();

它们三个的恩怨,如情丝,似乱麻,欲理,更乱。再写个十天十夜也就那样了,所以收工。

原创粉丝点击