逃不掉的语法小技巧 指针
题单介绍
(某CQ真的没学过指针)
C++有一种叫做STL的东西,动态数组、一些基础的数据结构里面都是有的,十分的方便,所以某CQ从来没有学过指针这种东西,虽然有时候会用到,也只是简单的强记一记而已(比如说scanf)
但是我们学的不是C++,而是C。
要写动态大小的数组,那只有我们自己动手来搞,这个时候指针便不得不用了,因为只有通过指针将每一个元素连接起来,我们才可以建成一个数组。
取地址:
当我们想要获取某个变量的地址,首先找到这个变量的变量名,我们假设它是a,如果你在这个变量名前面加上&(&a),那么恭喜你,你成功的取出了a这个变量的地址。
特别地,如果是一个一维数组,那么它的数组名就是指向它第一个元素的地址,这也是为什么scanf某个字符数组的时候不一定要加&
存地址:
现在你成功的取出了某个变量的地址(假设是一个int变量),你现在想把它存下来,以方便在其它函数里面找到这个变量,怎么办呢?
你可以用int *p;来新建一个指向int的指针变量。
这里的*号指的是你告诉编译器你新建了一个指针变量,这点要注意,因为一会这个符号还有另一个含义。
另外,我们建立的是指针变量,它本质上是一个存储地址的变量,和指针的含义并不相同。
用地址:
我们现在得到了变量a的地址,并把它存在了p1这个指针变量里面。我们怎么来使用p1呢?
这里我们又要用到*号
当我们在定义过p1指针后再次使用*p1,它的含义就发生了改变。
这里的*p1指的是p1这个指针指向的变量,也就是说——
*p1实际上指的就是a,无论你在什么地方修改了它的值,a的值也会随之发生改变。
那么借助指针的这个性质,我们可以写一些更方便的函数来让我们的代码更加简洁。
比如交换两个数,这个操作在某些问题中很常用,我相信大家都不想到处花上好几行的代码来实现它,那么我们可以这样写:
```c
void swap(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
//在main函数中↓
int a = 1, int b = 2;
swap(&a, &b);
//结果:a = 2, b = 1
```
通过使用指针,我们可以利用这个swap函数来将某个和这个函数没有半毛钱关系的变量交换值。
开一个指定大小的数组:
翻找C Reference(https://en.cppreference.com/w/c/memory)我们可以找到malloc这个函数和free这个函数,这两种函数是我们经常可能要用到的。
当我们想要开T类型的大小为num的数组,我们首先要通过malloc(size)申请一块size大小的内存,malloc函数会返回指向这个分配的内存的开头的指针,如果你注意看上面所提到的,你会发现这个实际上也就是数组名的含义,所以malloc我们是这样用的:
```c
T *p = malloc(num * sizeof(T));//sizeof就是获取里面给它的东西到底要占多少内存,这里给它变量类型,它会自己算
for (int i = 0; i < num; ++i)
p[i] = i;//随便瞎初始化
```
free(pointer)这个函数就是用来释放内存,当你所开的某个数组不会再用到了(比如说归并排序里面那个临时的数组),你需要把它的内存释放来优化你的内存占用,这个时候你就得通过free来把释放某个指针指向的数组。
比如说我们上面开了p这个数组,那么我们就使用free(p)来释放这个数组占用的内存。
这个题单就是把指针的用法讲一讲,并不会选题目进来。
指针的用法在C语言当中是逃不掉的,某CQ死赖了半天,发现不学还真的不行,所以各位一定要记好了,这真的十分重要!
顺带一提,我们知道数组的名字就是指向它第一个元素的指针,那么数组到底是什么意思呢?
原来,数组后面方括号里面的数字实际上指的是相对于这个数组指针在内存上的偏移值,偏移0那就是第一个元素,偏移1那就是第二个元素,以此类推。