众所周知,C语言之所以流行,有在于它的指针这一部分;在学习过程中,我们通常对指针的部分的把握难以强化,在此,我将我的经验写出来,分享给大家,供大家理解,欢迎大家斧正;
一、指针简述:首先我们要明了的是指针是一个特殊的变量类型;与int , float , double等函数类型是一个种类,不过装的是地址这样一个特殊分出来的变量;
由此处来看,我们是否可以猜想一下,对于指针的声明是否最初的想法就是 * p 这样一个东西(一个* 代表指针变量,后面跟其他一样是变量的名字),但是为什么正常的声明是一个现在这样的形式呢? (int *p)这样的呢?
这里就涉及到数据的储存的方式了;
二、数据的储存:首先,我们要明白对于内存的分割是将其变成一个个可以装 1Byte(8bit) 数据的一个小仓库,并且将一个特定的标识赋予这个仓库(也就是地址);
另外,我们需要知道的是,对于(int float double char)的储存都会给它一个特定的空间大小,比如 int 就是4Byte ,也就是32位,也因为此限制了数据的一个大小也就是无符号的int 在-2^31 ~ 2^31 - 1范围内 ,这是题外话;
我们回到指针,正因为他们会被分配几个这样的空间,因此它就会有几个对于的地址,但是我们又想通过地址来访问这个数据(不可能对这个数据的几个对应的地址都取出来,这样反而复杂了),因此加上了 int 这样一个数据类型标识对*p,告诉系统通过这个数据的首地址是去取int对应的空间大小的东西;
三、指针的初始化:首先,我们来定义一个指针变量,int *p;
1.int *p = &a ;
在定义时你这样初始化是可以成立的,是赋予p , a的地址;
(注意a的类型必须与指针的类型一样)
但是对于*p = &a;是绝对不行的,这样的话,就是p指向的内容是&a,而不是p保存a的地址,根据此我们可以下面这样定义;
2.p = &a;
这里我提醒一下,对于p,这是一个储存地址的变量,只能储存地址!而*p是指向p保存的地址的对应存放的内容;
3. int a[10];
int *p = a;
这里这样的初始化是对于一个数组而言,因为a就是他们的首地址;
同时给你们说一下,对于数组的 [ ] 这个符号他就是一个运算符,就是变址运算符(也叫下标运算符),对于a [ 8 ] 的 *** 作就是处理成 *(a + 8);
四、值得注意的是:
1.对于数组的名字a (这里取前面的定义), 它是一个地址常量,就是一个不变的量,你可以理解成 #define 的一个东西 无论怎么样都不能改变它,所以你不能进行 a ++ 将他作为一个左值(就是赋值运算符左边的东西);
2.对于地址的获取是不能够采取 直接的给定一个数字的方式,例如 int * p = 1100001;这样是不行的,因为每次的运行都不能确定数据储存在哪儿;如果这样能用你就会导致非法访问的一个错误,将一些有数据的地方进行了数据的一个覆盖,导致有用的数据受损;
3.所以对于地址的获取,只能通过&(取地址符号),或者指针之间的互相赋值,以及对数组首元素的地址获取 = a(数组名字);
4.对于多个指针的声明:
不能认为是这样 int* a, b, p;这样的声明就是a是一个指针,对于 b, p是一个整型变量;
因此改成这样,int *a , *b , *p;这样才可以!!!!
五、指针的运算:在采用地址引用数组的时候,可以采用指针运算,去指向下一个数;
例如:
p + 1 就是指向下一个数组的元素;
值得注意的是:对于p + 1,这不是单纯的加上一个 1 ; 而是根据指向的类型:进行对地址的量 + sizeof(type_name) * 1;也就是说 p + 1 是 p + 4 * 1;
ps;另外给大家提一下二级指针:
这样的: int **p;给大家分享一个简单的记下的思路;
我们可以先将**p 与
int *p 对比一下,是不是一下子明了了,*p声明它是一个指针,而另一个* 是*p指向的内容是*这个类型也就是地址类型;
然后就将节后起来 int **p ;我们已经知道**p是一个指向的地址,我们可以将其比作
int *p 而 **p就是后面的*p 那么int就是**p指向的地址的数据是一个整型变量;
另外:不要误解*,我这里就是一个便于理解,*其实是一个间接运算符;
对于运算符不明了的,可以看看这篇:
C语言运算符
##大约第一篇就更新到这儿,欢迎大家关注后面的内容,如果有错误,欢迎大家提出!!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)