C/C++指针学习记录(一)
1、指针概述
- 在学习新的知识之前,我们先回顾一下已经学习了的知识。我们已经了解到,在C环境下,程序里面变量的值都是存储在内存里面。当我们要求执行的时候程序的时候,CPU才会来主动寻找存放数据那块内存,然后取出来执行。那么怎么唯一找到那块内存呢?是的,没错。我们通过内存单元地址号就可以定位相应的存储单元了。所以指针变量其实就是存储地址的一种变量。
- 接下来我们在谈一谈为什么我们要学习指针相关的知识。
情景1:只是需要一个变量来存储一个必须值。比如一个简单的循环。
#include <stdio.h>
int main()
{
//在循环里面定义一个临时整形变量。
for(int i=3,i>=0;i--)
{
printf("%d",i);
}
return 0;
}
#include <stdio.h>
int main()
{
//在循环里面定义一个临时指针型整形变量。
int i_=3;
for(int *i=&i_;*i>=0;*i--)
{
printf("%d\n",i);
}
return 0;
}
显然在这种时候,使用非指针变量会更加简单一些。
- 情景二:函数修改参数的值。
#include <stdio.h>
void fun(int A)
{
A=5;
}
int main()
{
int a=3;
fun(a);
printf("%d",a);
return 0;
}
运行结果
仅仅把这个参数传进去,可以看到最终的结果并没有改变。因为这样传参仅仅只是把参数的值赋值给了另外一个系统自动定义生成的变量。他们仅仅拥有相同的内容,存储空间不再同一个地方。所以只要我们不提供返回值,那么其实传入的参数更我们的运算过程并没有太大的关系。可以看一下调试的过程证实一下我们的想法。
很明显他们的地址不一样。CPU是通过地址来获取变量的值,如果地址不一样那么显然和我们的想法不一致。
如果我们想要对参数本身改变,那么就需要知道参数的地址,通过改变地址里面存储的值来达到我们的目的。
#include <stdio.h>
void fun(int *A)
{
*A=5;
}
int main()
{
int a=3;
fun(&a);
printf("%d\n",a);
return 0;
}
这样我们就可以通过传入一个指针变量参数来达到更改参数值的目的。因为只是为了讲懂这个知识点,所以用的例题也很简单。
当然其实我们还知道一种参入参数的方式来改变参数的值,那就是传引用。那么接下来我们看看传引用的本质。
#include <stdio.h>
//传引用的本质
void fun(int &A)
{
A=5;
}
int main()
{
int a=3;
fun(a);
printf("%d\n",a);
return 0;
}
我们先看一下,调试的结果:
主函数里面参数的地址:
函数里面参数的地址:
结果呈现的是通过传引用我们也可以直接将参数的地址传入函数。为了更加深入的研究我们可以看一下,我们程序的反汇编:
直接传入指针的汇编:
传引用的汇编:
直接传入参数:
这样的话,我们就可以很清楚地知道,其实传引用和传指针的原理是一样的。
-
情景三:创建动态数组。我们学习C语言的时候,环境是没有给我们提供动态数组这个类型的变量。所以当我们想要创建动态数组(** 链表 **)就只可以使用指针变量。
用指针创建:
#include <stdio.h>
#include <stdlib.h>
typedef struct ActiveArray
{
int a;
struct ActiveArray *next;
}AA;
int main()
{
AA *aa_head;//创建一个动态数组的头指针
int n;//确定动态数字的大小。
scanf("%d",&n);
aa_head=(AA *)malloc(n*sizeof(AA));//在内存申请相应大的空间。
free(aa_head);//在推中申请的空间一定要记得释放
aa_head=NULL;//设置指针指向NULL。
return 0;
}
当然我们还可以创建单链表,链表的使用可能是指针最常用的地方了,就之后在记录吧。