
文章目录
- 一. 前言
- 二. 进入正题
- 1. 声明指针
- 2. int * pa 和 int pa[ ]的区别
- 3. 访问数组和指针
- 4. 释放内存
- 5. 指针或者数组做函数参数
- 6. 指针做参数需要注意的问题
一. 前言
指针是什么,有些萌新一听到指针就开始畏惧了,这种畏惧并不是来自指针给你的,而是他人给你的。我相信基本所有人都会在刚学习的时候百度:C语言最难的是什么?包括我。大多数答案告诉你指针最难,实话实说,指针确实难,但是是相对于其他知识点来说。通过网络上得到的一些信息,在没有学习指针之前,你便已经开始对指针存满了畏惧,在这里我想说,只有自己经历了才有资格去评价它其实单讲指针其实也没什么,前面学习的基本变量,整形,浮点型,字符型,等等,现在多了一个指针形,你只需要知道指针类型是用来存储地址的。地址也是一种数值,所以这没有什么难的,千万不要道听途说,要自己去证明。
二. 进入正题
1. 声明指针
//这就是指针的声明方式,对应的可以有如下几种形式,但不是全部:
int * p_1;
long * P_2;
char * P_3;
cout << sizeof(p_1) << " " << sizeof(P_2) << " " << sizeof(P_3);
大家认为上述三种指针类型各占多少字节? 答案是不论是什么类型的指针,都是占4个字节,因为地址用4个字节来存储是足够的,不要问为什么,我不知道。有时候,你只管像一个傻子一样去做事就好了。记住这句话。那有人又开始问了,既然都是4个字节,还分什么类型,只用一种类型就可以了啊。 一个最基本的答案是:地址虽然足以用4字节存储,但是数值不是,之所以有不同类型的指针,是为了让编译器知道从地址开始位置读取几个字节。 如果是char 则只读取1个字节,如果是int,就读去4个字节。现在明白了吗。 大家一定见过这样的例子:
int num = 123;
int * p;
p = #
我现在告诉你,是前者,但是两种写法都是合法的,我只是帮你理解指针,如果代码写成这样,会不会更容易理解点?
int num = 123;
int * p = #
p = #
这里有一个坑,需要注意:
int * P_1, P_2;
int *P_3, *P_4;
所以总结起来就是定义一个指针,int* p, int p, intp三种写法都是合理的。 但是如果连续定义多个指针,应将*和变量名挨在一起。
2. int * pa 和 int pa[ ]的区别
接着来说 int * pa 和 int pa[]的区别,这也是众多初学者的疑问,不管是数组或者指针,大多数情况下不可能存在于全局变量,讲之前再补充一点知识:
我们写的代码代码存储在包括栈区,堆区,数据区,代码区的地方,而全局变量存储在数据区,我们不做讨论 不使用指针声明的数组被称为静态数组,局部静态数组被存储在栈区 而使用指针声明的数组被称为动态数组,局部动态数组被存储在堆区 栈区(stack)由编译器自动分配释放,存放函数的参数值、局部变量的值等。 堆区(heap)用于动态内存分配。一般由程序员分配和释放,若程序员不释放,结束程序时有可能由OS回收。
int pa_1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int * pa_2;
pa_2 = new int;
int * pa_3;
pa_3 = new int(1);
int * pa_4;
pa_4 = new int[10];
int * pa_5;
pa_5 = new int[10]();
cout << *pa_2 << endl;
cout << *pa_3 << endl;
cout << *pa_4 << endl;
cout << *pa_5 << endl;
运行结果:

3. 访问数组和指针
访问静态数组和动态数组的不同,说之前再补一点知识,嘿嘿:
在Windows下,栈是高向低地址扩展的数据结构,是一块连续的内存的区域。 堆是向高地址扩展的数据结构,是不连续的内存区域,你们可以自行测试一下!
cout << pa_1[0] << endl;
cout << pa_1[1] << endl;
cout << pa_1[2] << endl;
cout << pa_1[0]++ << endl;
cout << pa_1[0] << endl;
cout << *(pa_5++) << endl;
cout << (*pa_5)++ << endl;
cout << *pa_5 << endl;
运行结果:

4. 释放内存
delete pa_5;
delete[]pa_5;
pa_5 = pa_1;
5. 指针或者数组做函数参数
int fun_1(int a[])
{
}
int fun_2(int * a)
{
}
int fun_3(int a[10])
{
}
6. 指针做参数需要注意的问题
int * end = NULL;
void func_1(int * end)
{
int * p = new int;
*p = 66;
end = p;
}
int * func_2(int * end)
{
int * p = new int;
*p = 66;
return p;
}
int ** end_2 = &end;
void func_2(int ** end_2)
{
int * p = new int;
*p = 66;
end_2 = &p;
}
不知道读者有没有想到一个常见的例子,用一个函数交换两个变量的值,变量作参数,这是值传递,我们知道函数内对传递过来的值作任何操作,对原值没有任何影响,于是我们引入指针,引入变量地址来解决交换,现在也一样,我们想改变一级指针,自然就需要二级指针来解决问题,所以,你明白了吗。
关于指针的应用还有函数指针,和指针函数,这两部分内容等写到函数的时候再详谈,再见咯。
(编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|