《算法笔记知识点记录》第二章——快速入门3[函数、指针](2)

简介: 《算法笔记知识点记录》第二章——快速入门3[函数、指针](2)

⚔️1.2 指针

🗡1.2.1 指针究竟是什么

先放上一张神图。大名鼎鼎的冯·诺伊曼体系结构。

f1cd2a5bfc609f263827fa98b112aa5.png

可以发现运算器能直接读取的程序是在存储器内的。那么运算器怎么拿到这个数据呢?

首先我们先明确,因为变量的读取都是从内存中的,所以一定会有一片空间在内存中。我们把它想象成有一栋公寓有一堆房间,我们想要找到我们的房间是不是得有个房间号?

19e66112d35f74aec6ad8735baae5c0.png

然后有没有发现102 103 104 105这四个房间我没画隔断,因为很多地方是按照门来编号的,但是一个大房间可能对应多个门呀。


上面的门的编号方式就是编制方式(可以一个门一个号,也可以两个门一个号),地址就每个门的房号,然后数据其实就是门内的内容。

我们根据房号找到家,计算机就是根据地址找到数据。

指针其实就是地址。也就是上面的房号。

我们假如忘了门号就看看外面门上的标识牌对吧?计算机内如果变量想要直到自己的地址也是需要看看自己的房号,怎么去看呢?用&,因为是变量自己看所以就是&x就拿到地址啦0.0

举个例子:


#include<cstdio>
int main(){
  int a = 0;
  printf("%d %d\n", &a,a);
  return 0;
}


输出结果可能是:2686748 1

其中地址是一个unsigned类型的整数(64位是unsigned longlong),至于为啥是无符号的,你见过谁家房号是负数么0.0


🛡1.2.2 指针变量

指针变量用来存放地址,然后可以看下图,就是指针变量,比较厉害,手里有把钥匙,并且这个钥匙可以开对应的门。

3e8c49fe11326fb3a28a7379bf626d1.png

然后由于这是一把钥匙,所以在声明它的时候需要在它前面加个*,表示它是一把钥匙。也就是int *p;,一般来说都是把*放在变量前面。

同时*也表示拿钥匙开门,*p就表示拿到对应的数据,所以图上的就是104号房间对应的元素。

刚才知道&是取地址,就是看看房间号,那么p = &a就可以把p这把钥匙变成a所对应的地址。此时再去*p就是a的值。

看下面的程序:


#include<cstdio>
int main(){
  int a;
  int *p = &a;
  *p = 233;
  printf("%d %d", *p, a);
  return 0;
}


输出结果是233 233,因为开房间的优先级很高,在赋值的时候是先打开门,再把数据写入,所以就把值写入到了a之中。最后输出就是两次a的值。


最后说明一下,不同的指针是不同的,比如下面的两把钥匙是不一样的。因为102-105是连着的,所以第一把钥匙钥匙+1实际地址会加4,而右边的指针对应的只有一个门,+1的时候只会加1,

其实对应的就是int *和char *类型的指针,其中一个长度为4,另一个为1。

这个指针的类型叫做基类型。

1cbadd7e38a885bd2da3b3b779fe02a.png

🔧1.2.3 指针与数组

之前有提到过数组就是一片连续的空间,数组名称也作为数组的首地址使用。

1fde4e5bca26b6dd29d5dd8442c28e2.png

根据上面提到的指针加1等于加对应的数据长度,所以a+i和&a[i]是完全相同的。

在枚举元素的时候可以这么写:


#include<cstdio>
int main(){
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  for(int *p = a; p < a +10;p+)
  printf("%d ",*p);
  return 0;
}


指针的减法


#include<cstdio>
int main(){
  int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  int *p = a;
  int *q = &a[5];
  printf("p = %d ", p);
  printf("q = %d ", q);
  printf("q - p = %d",q - p);
}


输出结果是:p = 2686688 q = 2686708 q - p = 5

会不会感觉震惊?这个q-p竟然不是20???,其实指针的减法是计算两个指针直接差多少个基类型,因为是int所以返回的就是相差多少个int。

⚒1.2.4 使用指针变量作为函数参数

指针变量也可以作为函数的参数,这时会把变量的地址传入函数。如果在函数中对这个地址中的元素进行修改,那么原本的数据也会修改。

例如:


#include<cstdio>
void swap(int *a, int *b){
  int temp = *a;  
  *a = * b;
  *b = temp;
}
int main(){
  int a = 1, b = 2;
  swap(&a,&b);
  printf("%d %d",a , b);
  return 0;
}


结果就是2 1,是不是就做到了?但是为啥呢?我们来看看这个过程

ee71f3e4c41a867feb2ee288f544e4c.png

可以发现在执行的过程中,swap直接改的就是原内存空间的值,当然改成功啦0.0


我们再看一个错误写法:


void swap(int *a,int *b){
  int *temp = a;
  a = b;
  b = temp;
}


这个如果看图就是讲swap调用栈里的a和b的值改了,并没有对之前的a和b造成任何影响。


🔨1.2.6 引用

引用是C++中一个强有力的写法,引用时候不产生副本,只是给原变量起了个别名。对引用变量的操作就是对原始变量的操作。

看一个例子:


#include<cstdio>
void change(int &b){
  b = 1;
}
int main(){
  int x = 10;
  change(x);
  printf("%d\n",x);
  return 0;
}


上面打印的结果就是1。

其实底层实现的话就是使用的指针,我猜想应该是使用的不可修改指针进行实现的。感兴趣的话可以看看这篇博客。理解C++中引用的底层实现


但是要注意:


#include<cstdio>
void swap(int &a, int &b){
  int temp = a;
  a = b;
  b = temp;
}
int main(){
  int a = 1, b = 2;
  swap(&a,&b);
  return 0;
}


上面的写法会直接报错,因为a和b的地址都是常量,所有声明的变量的地址都是常量不可进行修改!!!所以引用的时候不能传入变量的取地址。


关于指针的一些知识点我写了一篇文章做总结,如果大家有兴趣的话可以去阅读一下,保证会有更深的理解0.0

关于室友收租懂了指针那点事


🐳课后习题

今天的题目难度也不高,也不老多 哈哈哈哈哈,我写完会放题解,大家写完了可以在评论区打卡哟!我觉得,题解我放评论区吧,这样不用修改文章。(大家有问题可以联系我,今天太晚了,题解等明天把)


题目

2.6小节——C/C++快速入门->函数

2.7小节——C/C++快速入门->指针


相关文章
|
2月前
|
存储 算法
算法入门:专题一:双指针(有效三角形的个数)
给定一个数组,找出能组成三角形的三元组个数。利用“两边之和大于第三边”的性质,先排序,再用双指针优化。固定最大边,左右指针从区间两端向内移动,若两短边之和大于最长边,则中间所有组合均有效,时间复杂度由暴力的O(n³)降至O(n²)。
|
2月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
188 1
|
6月前
|
存储 C语言
指针的函数传参的详细讲解(一)
本文介绍了计算机内存管理与C语言中指针的基本概念及应用。从内存单元的划分到指针的定义,解释了指针作为地址的作用及其数据类型特性。文章通过代码示例详细说明了一级指针、二级指针的使用方法,以及`void*`指针的特点和限制。此外,还探讨了指针运算规则、函数指针传参解引用的原理,并结合链表实例分析了一级与二级指针在实际场景中的区别。最后附带两道指针练习题,帮助读者巩固理解。
141 0
|
12月前
|
算法 容器
【算法】——双指针算法合集(力扣)
移动零,复写零,快乐数,盛最多水的容器,有效三角形的个数,和为s的两个数(查找总价格为目标值的两个商品 ),三数之和,四数之和
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
256 4
|
存储 C语言 C++
如何通过指针作为函数参数来实现函数的返回多个值
在C语言中,可以通过将指针作为函数参数来实现函数返回多个值。调用函数时,传递变量的地址,函数内部通过修改指针所指向的内存来改变原变量的值,从而实现多值返回。
|
存储 搜索推荐 C语言
如何理解指针作为函数参数的输入和输出特性
指针作为函数参数时,可以实现输入和输出的双重功能。通过指针传递变量的地址,函数可以修改外部变量的值,实现输出;同时,指针本身也可以作为输入,传递初始值或状态。这种方式提高了函数的灵活性和效率。
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
556 1
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
314 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
1143 13

热门文章

最新文章