设为首页 加入收藏

TOP

指针和数组的掌握以及内存的管理(一)
2016-05-01 02:25:03 】 浏览:1110
Tags:指针 掌握 以及 内存 管理

前言:对于C语言的学习,我记得最初就有人说最难莫过于指针,当初我们的学习呢,又是先学习了数组,然后接触的就是指针,指针和数组被很多书籍放在一块进行教学,指针是C/C++中的精华,而难点就在于对指针和数组的掌握以及内存的管理,所以在这里,我们要对这个问题,进入一些研讨:

1 .什么是指针

在探究之前我们要弄清楚指针的概念,

指针做什么
int *p;

学过C的人都应该知道,这定义了一个指针,在这里p到底是个什么东西呢?
其实,p也就是一个变量,而对于变量,就可以理解为一个左值,会开辟一块内存空间,然后在这块空间中储存内容。

理解指针
int *p;
int a=10;
p=&a;

在这几句话,也不难理解,正因为像咱们在上面说的。开辟好了p这块空间,所以咱们现在就要在这块空间中,存放内容,而这个内容,在这里&a,也就是a的地址了。
如果你还不能理解,那么我用图来给你解释:
这里写图片描述
我想这样你应该会理解指针的作用,即存放地址。对于上面那个例子,p这块存放地址的空间我们叫做指针变量,p中存放的内存地址处的内存我们就称为p所指向的内存,通常我们也会说p指向了a。

“*”的作用

对于上面的理解,我们留下一个问题,就是“* ”,在定义一个指针时,我们需要加“ *”,而在使用时,我们也会加“ *”。
比如下面这段程序:

int *p;
int a=10;
p=&a;
*p=20;

“* ”我们就可以理解为,当一个基本的数据类型加上它时,这样就会构成一个数据类型的指针,这个指针我们要记住,大小永远是4个字节。而当我们写成 p 这样的形式时,我们在这里,称呼 *为解引用。就好像你现在手中会有一把钥匙,可以去通过指针来改变它所指向的那块空间的内容。

2.什么是数组

数组概念

数组,我们通常会理解为一组类型相同元素的集合。
比如:

int arr[]={1,2,3,4,5};

学过C的人应该都知道,这意思就是定义了一个数组,其中包含了5个int类型的元素。
这里写图片描述
当定义数组时,编译器会根据元素的个数和元素类型确定大小开辟空间,比如,上面的arr,我们就会分配20字节大小个空间。在这里,这块空间是不能再次改变的。

乱乱的&arr和&arr[0]
对于数组,我们一定要清楚&arr和&arr[0]这两个概念,&arr,这里说的就是对整个数组取地址。而&arr[0]在这里所说的也就是对数组的首个元素的地址。 &arr和&arr[0]这两个值是相等的,虽然他们相等,但是意义是不一样的。这个的区别就好比陕西省政府与西安市政府,他们的所在地都一样,都是在西安,但是意义不一样。

数组名的左值右值
左值和右值,简单说就是可以出现在“=”右边的就是右值,可以出现在“=”左边的就是左值。左值,他要是一块可以被修改的空间,右值,所说的值一块空间中所带的内容。

接下来我们要探讨一个问题了,数组名可以做左值吗?右值呢?

当arr作为右值时,我们要清楚,arr就是代表首元素的地址,在这里的arr就相当于arr[0]。
而当arr作为左值呢,在这我们就要根据左值右值的概念考虑了,左值必须是一块可以修改的空间,而这里,arr待变的是arr数组首元素的地址,地址不能被修改,所以,arr是不能作为左值的。

3.指针数组之间的联系

在我当初学习指针和数组时,总会觉得他们之间有种关系,并且好像彼此之间是一回事,在这里,我要告诉你,指针和数组之间是没有任何关系的!!!

很多人容易把这两个概念弄混淆很大的原因就是应为在访问时,指针和数组他们总是可以达到一样的目的。
例如:

char *p="abcdef";
指针形式和下标形式访问指针

对于上面的的指针变量p,根据前面咱们分析的可以知道,p是一块4个字节大小的空间,里面存放了首字符的地址。
比如我们需要访问’c’:

指针形式:*(p+2);这个意思就是先取出p的地址,然后给它按照字符型进行偏移2次,然后把所指向的地址进行解引用,访问其中所存放的内容。

数组下标形式:p[2];这里编译器会把下标形式解析成为指针形式的操作。这里的意思就是先取出p中存储的地址值,再加上其中括号中2个元素的偏移,得出新地址,然后再取出内容。

这两种方法最后使得我们所得到的结果都是一样的,两种方式本质上都是以指针为形式进行访问。

指针形式和下边形式访问数组
char arr[]="123456";

在这里我们需要访问’3’

指针形式:*(arr+2);这里就是得到arr的首字符地址,然后偏移两个字符,然后得到所指向地址,然后解引用,得到其中的内容。

数组下标形式:arr[2];这里编译器会把下标形式解析成为指针形式的操作。首先得到arr首元素的地址,然后偏移两个字符,得到新的地址,再取出内容。

经过了上述两个过程的分析,我们应该都知道指针和数组就是两个不一样的东西,他们只是可以”以指针的形式“和”以数组下标形式“来进行访问。

区分a与&a
首先我们通过牛客网的一道题来进行分析:
#include
   
     int main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d,*(a+1),*(ptr-1)"); return 0; }
   

在这里我们要分析:
&a+1:这个说的就是取了a的地址,然后向后偏移一个int,也就是到了这个数组最后一个位置的下一个地址。
(int )(&a+1):这个意思是将上述的地址强制转化为int 类型的地址。
所以执行完第二句话后,这里的ptr中存放的就是a这个数组的下一个数组的首地址。
这里写图片描述
*(a+1):这个的意思参考上面咱们分析的,所以也就可以得到这个的结果就是数组第二个元素。
所以,最终输出的结果也就是2和5;
这里我们依然强调一下&a说的是数组的地址,对他+1指的是偏移整个数组。
a这里代表的是a[0],首元素的地址。

4.指针数组和数组指针

指针数组:这里强调的是数组,然后数组中的元素都是指针,数组的大小是通过数组本身来决定。
数组指针:这里强调的是指针,就是说它还是一个指针变量,只不过他指向数组,至于他所指向的数组多大,这个就不知道了。

int *p1[5];
int (*p2)[5];

在这里我总结下来,指针数组和数组指针主要的区别主要是看优先级结合。”()”的优先级是最高的,下来是”[ ]”,再下来是”*“;

int* p1[5]:我们可以理解为,先于[10]结合,就是一个数组p1,然后是和”int*“结合,就表示数组中的内容全部都是int*类型的,所以这就是一个指针数组,数组中包含的是10个指向int类型数据的指针。所以他就是一个指针数组。

int (*p2)[5]:这里首先优先级最高的是”()“,所以先结合”()“,就是强调了这是个指针,然后和”[10]”进行结合,所以p2就是一个指向一个包含10个int大小的数组的指针。所以他就是一个数组指针。

这里写图片描述

5.函数指针,函数指针数组和函数指针数组指针

通过刚才对于指针数组和数组指针的理解,接下来我们来探讨一下函数数组和函数指针。

函数指针


什么是函数指针?

函数指针:顾名思义,这里强调的依然是指针,函数指针也就是说函数的指针,他是一个指向函数的指针。


char *fun3(char *p1,char *p2);

这个我想大家再熟悉不过了,函数为fun3,两个c

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇编写高效的C程序与C代码优化 下一篇青蛙跳台阶

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目