指针深度解剖,从内存详细了解指针

news2024/11/19 22:36:01

目录

    🚕第一组:一维数组

    🚌第二组:字符数组 

    🚐字符数组1.0

 🚎字符数组1.1

    🚑字符数组2

    🚚字符数组3

    🚜第三组:二维数组 

    🚗在上次的博客之中我们初步介绍了主要有哪些指针,在本次的博客当中我们通过多组示例来了解指针的深度解析,相信大家在阅读完这篇博客之后一定可以有不一样的收获。

    🚕第一组:一维数组

//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));

    🚓我们先从简单的一维数组的解析开始入手,我们利用 sizeof 操作符探究一下相关数据在内存中所占的空间的大小:第一个是 sizeof(a); 我们从上面可以看到的是,a 是一个有四个元素的一维数组,我们的数组名在正常情况下表示的都是第一个元素的指针但是在两种情况下表示的是整个数组。

     1.sizeof (数组名),数组名表示的是整个数组,sizeof 计算的是整个数组的大小,单位是字节。

     2.&数组名。数字组名表示的是整个数组,取出的是整个数组的地址,这个我们在介绍数组指针的时候介绍过。

    🚓在知道了上面两种数组名表示整个数组的两个情况之后,我们 sizeof ( a )的大小理解起来就简单多了。我们 sizeof (a) 求得的是整个数组的大小,也就是四个整形所占的字节数——16字节。

    🚓下一个 sizeof (a+0)。当我们sizeof当中只有数组名的话数组名表示的就是整个数组,但是一旦多了其他东西,都表示的是第一个元素的地址。所以我们的sizeof(a+0)表示的就是第一个元素的地址,地址的大小在不同机器上的大小不同,在32位机器上的大小为4字节,在64位机器上的大小为8字节。所以我们sizeof(a+0)求得的大小就是4/8字节。

    🚓sizeof(*a) 我们在上面说到了sizeof 只有在括号里只有数组名的时候表示的才是整个数组,但是这个括号里面还有一个 * ,所以 a 表示的是第一个元素的地址,所以我们的 *a 表示的就是第一个元素,一个整形所占内存的大小位四个字节,所以我们的 sizeof(*a) 求得的结果就是四个字节。

    🚓sizeof(&a) : &a表示的是取出一个数组的地址,但是其真正意义表示的还是一个地址,之哟啊是地址,所以在内存中所占的大小就为4/8个字节。这个其实并不是重点,重点是下一个:sizeof(*&a)。在上面我们直到 &a 表示的是一个数组的地址,那么*&a表示的就是将这个数组指针解引用找到的就是这个数组,我们可以将 * 和 & 当作是一组互逆的符号,可以相互抵消,所以我们可以认为 * 和 & 符号抵消了,sizeof(*&a)也变成了sizeof(a),sizeof括号里面有一个数组名,表达的是整个数组,求得的就是我们整个数组的大小:16个字节。

    🚓本组最后一个sizeof(&a+1):我们的&a表示的是一个数组的大小,所以我们 +1 之后会直接跳过一个数组的大小,指向后面一个内存大小和前面数组一样一个地址,但是也是一个指针,只要是指针在内存中所占的大小就是4/8个字节。上面的程序运行效果如下:

    🚌第二组:字符数组 

    🚐字符数组1.0

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));

    🚘在我们分析完一维数组之后我们就需要将我们的注意力转向我们的字符型数组了。我们都知道的是字符数组有两种表现形式,相对应的这两种不同的表现形式对应着不同的运行效果,我们就来一个一个进行分析。

    🚘我们的arr是一个字符型数组,sizeof(arr) 还是像我们上面所说到的那样求得是一个数组所占内存空间的大小:也就是六个字节。

    🚘sizeof(arr+0) 括号里并不只是有数组名所以表示的就是数组的首元素的地址,+0 得到的结果是第一个元素的地址,只要是指针那么所占内存的大小就是4/8个字节。

    🚘sizeof(*arr) 括号中并不是只有数组名,所以表示的就是我们数组中第一个元素的地址,然后解引用得到的就是数组中的第一个元素,在内存中所占的大小也就是一个字节。

    🚘 sizeof(&arr) :&arr 取出的是整个数组的地址,但是只要是地址在内存中所占的空间的大小就是4/8个字节。sizeof(&arr+1)我们&arr取出的显示一个数组的地址,然后再 +1 就跳过了一个数组的大小,所以我们的(&arr+1)表示的就是我们跳过一个数组之后的地址。一个地址在内存中所占的大小位4/8个字节。

    🚘sizeof(&arr[0]+1) : 我们的数组名由于优先级先和 [ ] 相结合,表示下标为0的元素,然后&取出的是第一个元素的地址,之后再 +1 得到的就是数组中第二个元素的地址。地址所占内存的大小为4/8个字节。上面的程序的运行效果如下:

 🚎字符数组1.1

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));

     🚔我们有的小伙伴们可能会想:这不是和上面的一样吗?NONONO,让我们仔细来分析分析。我们上面的 sizeof 求的是数据所占内存的大小,我们的strlen求的是 ‘\0’ 之前的字符的个数,所以我们需要记住的是 ‘\0’ 很重要。我们就带着这个去进行代码的分析:strlen(arr),求的是数组中的字符个数遇到 ‘\0’ 停止,但是我们的数组并没有 ‘\0’ 我们的字符串数组有两种书写形式,我们知道的是当我们使用单引号一个字符一个字符进行列举的时候我们数组中并不会附加上 ‘\0’ 所以我们的strlen库函数就会一直向后查找数组中的元素直到遇到 ‘\0’ 为止,(也就是0)但是我们数组一旦越界之后的值就是随机值了,什么遇到0我也不知道,所以我们strlen求出的就是一个随机值。

    🚔strlen(arr+0) 在分析这个式子的时候我们先来补充一个知识:也就是strlen函数的基本原型。

    🚔上面我们可以看到的是strlen函数的形参部分是一个char类型的指针,我们再向函数传输一个字符型指针之后就会向后进行查找之后遇见 ‘\0’为止。那么我们回过头来分析这个题目:strlen(arr+0)。arr+0表示的是首元素的地址,即一个char类型的指针,也就是说我们的strlen函数需要从数组中的第一个元素开始向后进行查找直到找到 ‘\0’ 为止。经过上一条分析之后我们可以知道的是strlen(arr+0)的到的值也是一个随机值。

    🚔strlen(*arr) : 我们的*arr得到的是第一个元素也就是 ‘a’ 但是我们经过上面的函数原型可以知道的是strlen函数的形参为一个函数指针,而我们要是向函数中传一个字符作为参数的话那么就会出现错误,因为我们的字符 a 实质上就是一个ASCII码值,当我们将这个ASCII码值作为参数传给strlen时我们的程序就会将传入的ASCII码值当作一个地址读取,进而导致非法访问。进而系统报错。

    🚔strlen(&arr) :我们的&arr表示的是整个数组的地址。但是这种作用形式只会再数组加一的时候体现出来,我们的&arr得到的值和我们的首元素的地址相等。虽然&arr的数据类型为char(*pa)[6]但是会发生隐式转换,只会有一个警告,系统就将我们的&arr的值转换成char*类型的数据了。所以我们得到的结果也是从数组首元素开始到 ‘\0’ 结束的长度。由于没有 ‘\0’ 所以就为随机值。

    🚔strlen(&arr+1) 我们经过上面的分析之后可以知道的是&arr表示的是整个数组的大小 +1 之后会跳过整个数组的长度。之后经过隐式转化之后从数组的末尾开始查找 ‘\0’ 。我们得到的结果也是一个随机值,只不过这个随机值比上面的随机值小一个数组的长度。

    🚔strlen(&arr[0]+1) 这个和我们上面的分析方法是相同的。arr先和我们的 [0] 相结合表示数组的第一个元素,之后再取地址表示第一个元素的地址,类型为 char* 之后 +1得到的是第二个元素的地址。与我们的strlen函数的参数刚好相符。所以我们的strlen函数求得就是从数组第二个元素开始查找直到 ‘\0’ 为止,答案是一个随机数且比strlen(arr)得到的结果小1。上面我们的代码的运行结果也就可以得出:

    🚑字符数组2

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));

    🛹当我们使用双引号直接引出一个字符串的时候我们得到的是我们给出的字符串+1。数组中会隐形的含有一个 ‘\0’ 用于表示字符串的结束。所以我们在使用sizeof 和strlen进行计算的时候就绪要格外地进行注意。就像是我们的sizeof(arr)表示的就是我们的整个数组的大小 ”abcdef“ 外加上 ‘\0’ 所以我们得到的结果就是7个字节。

    🛹我们的strlen(arr)表示的是从数组首元素开始到 ‘\0’ 结束计算字符的个数。由于我们的数组之中带着一个隐性的 ‘\0’ 所以我们的结果为6。

    🛹strlen(arr+0)表示的和我们的上面的strlen(arr)一样都是从首元素开始计算字符串的长度,所以大小也为6。

    🛹strlen(*arr)表示的是我们数组的首元素,因为一个字符即一个ASCII直接进行传参会产生非法访问,所以我们的系统会报错。

    🛹strlen(&arr) 和我们上面分析的一样,也是整个元素的指针进行隐式强转最终的到一个首元素的地址。唯一不同的就是我们在这里有 ‘\0’ 所以我们的答案不再是随机值而是我们字符串的长度6。

    🛹strlen(&arr+1)这个式子的分析结果就和我们这组分析的结果大不相同了。我们先&arr得到整个数组的指针然后 +1 得到的是跳过整个数组的指针(跳过七个元素”abcdef“和'\0')然后我们再向后查找 ‘\0’ 由于我们数组后面的值并不确定所以得到的答案是一个随机值。

    🛹strlen(&arr[0]+1)这个式子的分析过程就不像是我们上面的分析那么离谱了,就又变回了循规蹈矩的步骤:数组名先和 [0] 结合得到第一个元素然后再取地址得到第一个元素的地址,+1 之后得到第二个元素的地址。所以我们这个式子得到的结果就是从第二个元素开始一直到 ‘\0’ 为止的字符个数,也就是5。我们上面的程序演示结果如下:

    🚚字符数组3

char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p[0]+1));

printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));

    🚲假如我们将我们的字符串放到一个指针变量中再进行求值呢?会有什么不一样吗?我们继续来接着分析:

   🚲 sizeof(p) 一个指针的大小都为4/8个字节。

    🚲sizeof(p+1)表示的是 第二个元素的指针也就是4/8个字节。

    🚲sizeof(*p)得到的是一个字符型元素所占内存的大小也就是一个字节。

    🚲sizeof(&p)我们的p表示的是一个指针然后再重新进行&操作得到的就是一个二级指针。二级指针同样是一个指针,所以我们得到的结果同样是4/8个字节。

    🚲最后一个式子sizeof(&p[0]+1)我们p[0]表示第一个元素怒然后&得到第一个元素的地址+1得到第二个元素的地址,地址的大小再内存中都占4/8个字节。

    🚲之后就到我们的strlen组的分析了。strlen(p)由于p代表的是字符串首个字符的地址,所以我们的strlen可以正常接收得到的结果是6。

    🚲strlen(p+1)向后跳过一个字节的大小得到第二个元素的指针最终得到的结果是5。

    🚲strlen(*p)我们*p将指针p解引用得到第一个元素,会产生非法访问,系统会报错。

    🚲strlen(&p)我们&p得到的是一个二级指针。我们strlen库函数实质上会在函数中进行一次类似于解引用的操作得到字符,但是我们的二级指针经过一次解引用之后得到的结果依旧是一个指针(地址),所以我们的库函数会将我们解引用之后得到的地址认为是一个字符和我们的 ‘\0’ 进行比较。如果相等就表示字符串结束这里由于是系统随机分配地址所以我们的到的答案依旧是随机值。

    🚲strlen(&p[0]+1)我们的数组名会先和 [0] 结合表示数组的第一个元素。然后&表示第一个元素的地址,之后+1得到的就是第二个元素的地址,strlen函数会从第二个元素开始进行查找,结果是5。我们上面的程序运行效果如下图所示:

    🚜第三组:二维数组 

//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));

    🛵接下来我们就来到了我们最重要的一部分:二维数组的内存指针相关解析。废话少说我们直接来看例题:sizeof(a)我们的数组名依然表示的是整个数组,我们的二维数组当中一共有12个元素,给个元素的类型都是 int 所以我们的到的结果就是48。

    🛵sizeof(a[0][0])表示的就是第一个元素,也就是sizeof(int)我们得到的结果自然也就是4。

    🛵注意我们的难点来了:sizeof(arr[0]),我们可以将我们的二维数组看成一个由数组组成的新的数组,如a[3][4]={0}={ {0,0,0,0} , {0,0,0,0} ,{0,0,0,0} };所以说我们的a[0]相当于我们的第一个数组元素也就是{0,0,0,0},同时我们的a[0]也可以理解成一个新的数组名即a1,那么我们的sizeof(a[0])的大小就是16。

    🛵sizeof(a[0]+1)就像是上面我们所说的那样我们的a[0]可以理解成为一个新的数组名,那么要是有其他部分的话表示的就是首元素的地址,即第一行第一个元素的地址,之后再+1得到的第一行第二个元素的地址,地址的内存大小为4/8个字节。

    🛵sizeof(*(a[0]+1))我们的a[0]+1表示的是第一行第二个元素的地址那么解引用得到的就是第一行第二个元素。所以结果就是4个字节。

    🛵sizeof(a+1)同样的道理我们的二维数组也可以利用上面的规律,数组名单独出现的话就表示的是整个数组,只要有其他部分表示的就是第一个元素的地址,所以我们的a+1表示的就是我们的第二”元素“(第二行的数组)的指针。所以我们的答案是4/8个字节。

    🛵sizeof(*(a+1))我们上面说到了a+1得到的是我们第二行的数组的地址,所以我们再解引用得到的就是第二行的数组。答案也就是16个字节。

    🛵sizeof(&a[0]+1)根据我们的规律变量名先和[0]结合得到数组的第一行第一个元素的地址,然后再取地址得到的就是第一行数组的地址然后+1得到的就是第二行的数组的地址。地址在内存中所占的大小为4/8个字节。

    🛵sizeof(*(&a[0]+1))我们在上面的基础之上继续分析得到:第二行数组的地址进行解引用得到的就是第二行的数组的大小,所以我们的答案就是16个字节。

    🛵sizeof(*a)我们很容易地就能够发现数组名a并没有单独存在所以我们的a就理解为第一个元素即第一行的数组然后进行解引用得到的就是第一行的数组的大小。答案为16个字节。

    🛵sizeof(a[3])(注意:数组的下标的范围!)很多小伙伴们看到这里肯定会感到很好奇,这不是已经数组越界了吗?其实不然。我们在这里再进行扩充一个知识点:sizeof实质上是针对数据类型进行判断的,并不会对括号里面的式子进行运算。这是因为我们的sizeof操作符再编译的阶段就已经计算完毕了,但是我们等式的计算是在运行阶段才进行计算的。运行阶段在编译阶段之后。所以我们可以得到一个道理:sizeof不用考虑数组越界问题,他不会真的对数组进行检查,只会对数组的类型进行判断,换句话来说我们也可以将sizeof(a[3])写成sizeof(*(int(*)[4]))我们得到的结果依旧是一个元素个数为4的数组,因此我们的答案就是16个字节。我们以上程序的运行效果如下:

    🏍那么我们本次的博客也就正式宣告结束了,希望可以帮到大家,感谢大家的观看,祝大家天天开心。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/156978.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

INVS里的DanglingWire的自动化清理实战

在上一讲中一起了解了INVS里的DanglingWire(innovus中的DanglingWire(悬垂线)的理解和处理),常言道理论联系实际,在理解原理的基础上,那一定是要服务项目的,这篇后续火速跟进&#x…

中国第一个 Apache 顶级开源项目的突围之路!

【CSDN 编者按】近些年开源大热,开源创业之风随之四起。作为近两年特别火的商业方向,开源创业者如何才能在一片红海中乘风破浪,在行业中占据一席之地?第一个由中国人主导贡献到 ASF 的顶级开源项目 Apache Kylin 做出了有效探索&a…

字节序,主机字节序与网络字节序

📌————本章重点————📌 🔗了解字节序的概念; 🔗了解大小端的概念;🔗了解主机字节序和网络字节序的区别;🔗学习主机字节序和网络字节序相机转化的接口; ✨————————————✨字节序 概念&am…

人工智能助力古彝文识别,推动传统文化传承

人工智能助力古彝文识别,推动传统文化传承0. 前言1. 古彝文1.1 古彝文介绍1.2 古彝文识别的重要意义1.3 古彝文识别的挑战2. 古彝文识别国内外研究进展3. 基于深度学习的古彝文识别3.1 深度学习简介3.2 基于深度学习的古彝文识别模型架构4. 古彝文识别进展与展望小结…

HTML小游戏19 —— html5版开心斗地主小游戏(附完整源码)

💂 网站推荐:【神级源码资源网】【摸鱼小游戏】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】本节教程我会带大家使用 HTML…

【练习】Day05

努力经营当下,直至未来明朗! 文章目录一、选择二、编程1. 跳跃游戏[贪心算法]2. 寻找重复数[注意思路!]答案1. 选择2. 编程普通小孩也要热爱生活! 一、选择 HASH 函数冲突处理方式不包括以下哪一项:(&…

YOLOv5源码详解——项目目录

YOLOv5 目录 .github .github相关,不重要 datasets 存放数据集,刚下载下来的源码是不包含这个文件夹的 classify 图像分类模块,包含以下4个文件 predict.py —— 图像分类预测脚本train.py ——图像分类训练脚本val.py —— 图像分类验证脚本tutorial.…

Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发

一、标准CRUD使用 对于标准的CRUD功能都有哪些以及MyBatisPlus都提供了哪些方法可以使用呢? 我们先来看张图: 1.1 环境准备 这里用的环境就是Java开发学习(四十)----MyBatisPlus入门案例与简介中使用的环境 二、新增 在进行新增之前,我们可以分析下新增的方法…

马蹄集 公式计算

公式计算 难度&#xff1a;青铜 01 时间限制&#xff1a;1秒巴占用内存&#xff1a;64M 计算公式 (1/2)*(a*xc(ac)/(4*a)》 格式 输入格式&#xff1a;输入为整型x,a,空格分隔 #include <bits/stdc.h> using namespace std; int main() {int x, a;cin >> x >&g…

1、JDK17安装

目录 一、简介 二、安装步骤 三、在Windows 10系统中配置环境变量 四、运行jdk 一、简介 JDK全称Java SE Development kit(JDK)&#xff0c;即java标准版开发包&#xff0c;是Oracle提供的一套用于开发java应用程序的开发包&#xff0c;它提供编译&#xff0c;运行java程…

二叉树【数据结构】【超详细,一学就会!!!】

目录 &#x1f4d6;1.什么是二叉树&#xff1f; &#x1f334;2.满二叉树和完全二叉树 ⛳2.二叉树的性质 &#x1f525;3.二叉树的创建与遍历 3.1 创建二叉树 3.2 前中后序遍历——递归和非递归 &#x1f3f9;4.二叉树的实现 1️⃣获取树中节点的个数 2️⃣获取叶子节点…

MATLAB-三维插值运算

MATLAB中是支持三维及三维以上的高维插值的。三维插值的基本原理与一维插值和二维插值是一样的&#xff0c;但三维插值是对三维函数进行的插值。在MATLAB中&#xff0c;使用interp3函数实现插值&#xff0c;其调用格式如下。vi interp3(x,y,z,v,xi,yi,zi) %返回值 vi是三维插值…

2022ICPC杭州站

A. Modulo Ruins the Legend 题目链接&#xff1a;Problem - A - Codeforces 样例1输入&#xff1a; 6 24 1 1 4 5 1 4样例1输出&#xff1a; 1 0 5样例2输入&#xff1a; 7 29 1 9 1 9 8 1 0样例2输出&#xff1a; 0 0 0题意&#xff1a;给你一个长度为n的数组a[]&#x…

【NI Multisim 14.0原理图的设计——原理图分类】

目录 序言 一、原理图的设计 &#x1f34a;知识点&#xff1a; 二、原理图分类 &#x1f349;1.平坦式电路 &#x1f349; 2.层次式电路图 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电路设计和…

【用JS自制表格软件玩数据】10. 为表格脚本设计一个语法解析器

设计脚本语言的语法解析器概述脚本源码语法预览运行效果如下图设计计算符号的优先级定义一些关键词生成一份关键词的map方便引用枚举关键词的类型错误异常的捕获字符匹配代码的字符转化成迭代器关键词标记器词法分析器设计一个队列处理器源代码字符串迭代器代码的块级运行环境脚…

【HTML基础篇003】前端基础之CSS选择器大全

✨一、CSS的基本介绍 CSS&#xff08;Cascading Style Sheet&#xff0c;层叠样式表)定义如何显示HTML元素。 当浏览器读到一个样式表&#xff0c;它就会按照这个样式表来对文档进行格式化&#xff08;渲染&#xff09;。 ✨二、CSS的几种引入方式 &#x1f338;2.1、方法一&am…

连接查询之内连接(等值连接、非等值连接和自连接)

1、等值连接&#xff1a;表连接条件是等值关系&#xff0c;我们称为等值连接。 需求&#xff1a;查询每个员工所在部门名称&#xff0c;显示员工名和部门名&#xff1a; 查看员工表的ename和deptno字段信息&#xff1a; 查看部门表中的deptno和dname字段信息 SQL92语法&#x…

2023年最值得关注的机器人趋势TOP10

新兴的机器人技术趋势和预测满足了对工业自动化、数字化和可持续性的需求。仓库中的材料处理由自动移动机器人&#xff08;AMR&#xff09;和自动引导车辆&#xff08;AGV&#xff09;实现自动化。相关机构对8949家全球初创企业和2023年机器人趋势规模的样本进行了研究&#xf…

Linux的安装(云服务器专讲)

一、Linux环境的安装有一下几种方式&#xff1a;双系统或则将自己的笔记本搞成Linux系统——严重不推荐&#xff0c;这样安装成本高、并且容易把自己电脑弄坏。虚拟机推荐wmware player这是免费的&#xff0c;并且推荐是打在了centos7.x版本的&#xff0c;这个的好处就是不需要…

微信接入 ChatGPT(学习笔记,不作教程)

微信接入 ChatGPT前置条件接入前提去Linux虚拟机&#xff08;必须有go环境&#xff09;安装前先配置下ssh密钥生成新的ssh密钥检查将 SSH 密钥添加到 ssh-agent将 SSH 密钥添加到您在 GitHub 上的帐户上去github上将密钥复制在里面然后点击添加ssh密钥安转部署最后直接go run m…