进程与线程(三)

进程与线程(三)

  • 进程间通信
  • 传统间的进程间通信机制
    • 无名管道
      • 无名管道的特征
      • 无名管道的创建
      • 父子进程通信
      • 测试管道的大小
      • 管道读写易出现的问题
    • 有名管道
      • 创建有名管道
      • 有名管道的写端代码
      • 有名管道的读端代码
    • 信号
      • 信号的特征
      • 产生信号
        • 硬件来源
        • 软件来源
          • 发送信号的函数:kill() raise()
          • 定时器信号
      • 响应信号
      • 信号安装:
        • 忽略信号
        • 执行缺省操作
        • 捕捉信号

进程间通信

在这里插入图片描述
常用的进程间通信方式
1、传统的进程间通信方式
无名管道(pipe)、有名管道(fifo)和信号(signal)
2、System V IPC对象
共享内存(share memory)、消息队列(message queue)和信号灯(semaphore)
3、BSD
套接字(socket)

传统间的进程间通信机制

无名管道

在这里插入图片描述

无名管道的特征

这里所说的管道主要指无名管道,它具有如下特点:
1、只能用于具有亲缘关系的进程之间的通信
2、半双工的通信模式,具有固定的读端和写端
3、管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数。

在这里插入图片描述

无名管道的创建

在这里插入图片描述

父子进程通信

(1)创建无名管道
(2)创建子进程
(3)完成父子通信业务
通信流程:子进程发消息给父进程
思路:fd[0]读端 fd[1]写端 ----》固定的
子进程:发消息(fd[1]有效) fd[0]关闭掉
父进程:收消息(fd[0]有效) fd[1]关闭掉

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(int argc, const char *argv[])
{
	//1,创建无名管道
	//定义数组,存储读写的文件描述符
	int fd[2];
	if(pipe(fd) < 0)
	{
		perror("pipe error");
		return -1;
	}
	printf("pipe ok!\n");
	//2,创建子进程
	pid_t pid = fork();
	if(pid < 0)
	{
		perror("fork error");
		close(fd[0]);
		close(fd[1]);
		return -1;
	}
	else if(0 == pid)
	{
		//子进程的地址空间
		//关闭读端
		close(fd[0]);
		//发消息(write)
		//定义消息文本
		char Message[100] = {0};
		printf("请输入需要发送的消息:");
		fgets(Message, sizeof(Message), stdin);
		//使用write写入到管道中
		write(fd[1], Message, strlen(Message));
		printf("send ok!\n");
	}
	else
	{
		//父进程的地址空间
		//关闭写端
		close(fd[1]);
		//收消息(read)
		//定义接收消息的地址空间
		char Message[100] = {0};
		read(fd[0], Message, sizeof(Message));
		printf("来自于子进程:%s\n",Message);
	}
	return 0;
}

在这里插入图片描述

测试管道的大小

思路:往管道中不管写入,直到写不进去,此时写入的字节数就是管道容量大小

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main()
{
	//测试管道大小
	//创建管道
	int fd[2];
	if(pipe(fd) < 0)
	{
		return -1;
	}
	printf("create pipe ok!\n");
	//写入数据,不断写入
	//1KB == 1024byte
	char buf[1024] = {0};
	int size = 0;
	while(1)
	{
		int wr_count = write(fd[1], buf, 1024);//每次写入1024个字节 即:1KB大小
		if(wr_count < 0)
		{
			perror("write error");
			break;
		}
		else if(0 == wr_count)
		{
			printf("nothing wai be written...\n");
			break;
		}
		else
		{
			size++;
			printf("%dKB\n",size);
		}
	}
	close(fd[0]);
	close(fd[1]);
	return 0;
}

在这里插入图片描述

管道读写易出现的问题

当管道中无数据时,读操作会阻塞
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将会一直阻塞。
只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIGPIPE信号(通常Broken pipe错误)。

在这里插入图片描述
在这里插入图片描述

案例:验证管道断裂

#include <stdio.h>
#include <sys/types.h>
#inckude <unistd.h>
#include <string.h>
int main()
{
	int fd[2];
	if(pipe(fd) < 0)
	{
		return -1;
	}
	printf("pipe ok!\n");
	//关闭读端 (保证写入管道时,读端不存在---》才会出现管道断裂)
	close(fd[0]);
	pid_t pid = fork();
	if(pid < 0)
	{
		return -1;
	}
	else if(0 == pid)
	{
		//子进程
		//写入数据到管道
		char data[1024];
		printf("Please input:");
		fgets(data, sizeof(data), stdin);
		write(fd[1], data, strlen(data));
		printf("写入管道成功!\n");
		exit(100);
	}
	else
	{
		//父进程
		//使用wait阻塞等待子进程退出时回收其资源
		int wstatus;//保存子进程的退出状态值
		wait(&wstatus);
		//当执行该40行时,说明子进程已经退出(收到信号异常退出还是正常执行exit(100)退
		出?)
		//分类讨论
		if(WIFSIGNALED(wstatus))
		{
			//收到信号导致子进程退出
			printf("导致子进程退出的信号
			是:%d\n",WTERMSIG(wstatus));//SIGPIPE==13号
		}
		else if(WIFEXITED(wstatus))
		{
			//正常退出---》执行了exit(100)
			printf("子进程的退出状态数值为:%d\n",WEXITSTATUS(wstatus));
			//父进程
			char buf[1024] = {0};
			read(fd[0], buf, sizeof(buf));
			printf("读取的结果是:%s\n",buf);
		}
	}
	return 0;
}

有名管道

无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围
1、有名管道可以使互不相关的两个进程互相通信。
2、有名管道可以通过路径名来指出,并且在文件系统中可见
3、进程通过文件IO来操作有名管道
4、有名管道遵循先进先出规则,不支持如lseek() 操作

在这里插入图片描述

创建有名管道

在这里插入图片描述
在这里插入图片描述

有名管道的写端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	//创建有名管道(同时也创建好了管道文件)
	if(mkfifo("./fifo.txt", 0664) < 0 && errno != EEXIST)
	{
		perror("mkfifo error");
		return -1;
	}
	printf("mkfifo ok!\n");
	//以只写方式打开创建好的管道文件
	int fw = open("./fifo.txt", O_WRONLY);
	if(fw < 0){
		perror("open_write error");
		return -1;
	}
	printf("open_write ok!\n");
	char buf[1024] = {0};
	while(1)
	{
		//对于buf做清空
		bzero(buf, sizeof(buf));
		printf("客户端:");
		fgets(buf, sizeof(buf), stdin);
		//判断客户端是否办理完毕业务
		if(0 == strncasecmp("quit", buf, 4))
		{
			printf("业务办理结束!\n");
			break;
		}
		//发送消息
		int wr_count = write(fw, buf, strlen(buf));
		if(wr_count < 0){
			perror("write error");
			break;
		}
		else if(0 == wr_count)
		{
			printf("未写入任何内容...\n");
			break;
		}
		else
		{
			printf("实际发送%d字节内容!\n",wr_count);
			printf("send ok!\n");
		}
	}
	//关闭写端
	close(fw);
	return 0;
}

有名管道的读端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	//创建有名管道(同时也创建好了管道文件)
	if(mkfifo("./fifo.txt", 0664) < 0 && errno != EEXIST)
	{
		perror("mkfifo error");
		return -1;
	}
	printf("mkfifo ok!\n");
	//以只读方式打开创建好的管道文件
	int fr = open("./fifo.txt", O_RDONLY);
	if(fr < 0){
		perror("open_read error");
		return -1;
	}
	printf("open_read ok!\n");
	char buf[1024] = {0};
	while(1)
	{
		//对于buf做清空
		bzero(buf, sizeof(buf));
		//接收消息
		int rd_count = read(fr, buf, sizeof(buf));
		if(rd_count < 0)
		{
			perror("read error");
			break;
		}
		else if(0 == rd_count)
		{
			printf("客户端业务处理结束!\n");
			break;
		}
		else
		{
			printf("成功接收%d个字节!\n",rd_count);
			printf("来自于客户端:%s\n",buf);
		}
	}
	close(fr);
	return 0;
}

在这里插入图片描述

信号

信号的特征

信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式
信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。
如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程
同步:发送方发送数据,等待接收方响应之后才发下一个数据包的通讯方式
异步:发送方发送数据,不等待接收方发回响应,接着发送下一个数据包的通讯方式

产生信号

硬件来源

从键盘输入:
ctrl c : SIGINT信号 ,默认处理方式为进程终止
ctrl : SIGQUIT信号,作用与SIGINT类似,默认处理方式为进程终止
ctrl z: SIGTSTP信号,默认处理方式为进程暂停
SIGSTOP信号:只能通过kill产生,默认处理方式进程暂停

软件来源
发送信号的函数:kill() raise()

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
功能:不仅可以终止进程,也可以向进程发送其他信号
#include <signal.h>
int raise(int sig);
功能:只允许进程向自身发送信号

案例:首先使用fork创建子进程,在子进程中使用raise()向自身发送SIGSTOP信号,使子进程暂停;接下来在父进程中当时间戳超过10秒之后,调用kill()向子进程发送SIGKILL信号杀死子进程并回收子进程的退出
资源,且检查导致子进程退出是否因为收到了信号,如果是,打印出该信号是几号?如果子进程是正常退出,则打印出子进程退出的状态值是多少?(模拟正常退出:例如在终端给子进程发送SIGCONT信号来唤醒子进程,此时子进程继续执行,直到执行了exit()退出)

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/wait.h>
int main(int argc, const char *argv[])
{
	//功能:练习kill()和raise()
	pid_t pid = fork();
	if(0 == pid)
	{
		//子进程
		printf("child PID = %d\tparent PID = %d\n", \
		getpid(), getppid());
		//使用raise()函数给子进程自己发送SIGSTOP,让其暂停
		raise(SIGSTOP);
		printf("I am wakeup...\n");
		printf("hahahah\n");
		exit(88);
	}
	else
	{
		//父进程
		//定义保存时间的变量
		time_t start_time, current_time;
		time(&start_time);
		int wstatus;
		//回收子进程退出资源
		while(1)
		{
			//获取当前的系统时间(更新的)
			time(&current_time);
			if(current_time - start_time > 10)
			{
				//使用kill()函数给子进程发送SIGKILL信号,让其终止
				kill(pid, SIGKILL);
			}
			int exitID = waitpid(-1, &wstatus, WNOHANG);
			if(exitID < 0)
			{
				perror("waitpid error");
				break;
			}
			else if(0 == exitID)
			{
				printf("子进程还未结束...\n");
			}
			else
			{
				//已成功回收子进程
				printf("已成功回收子进程的退出资源...\n");
				if(WIFSIGNALED(wstatus))
				{
					printf("异常退出,造成子进程退出的信号是:%d号信号!\n",WTERMSIG(wstatus));
				}
				else if(WIFEXITED(wstatus))
				{
					printf("子进程正常退出,退出状态数值为:%d\n",WEXITSTATUS(wstatus));
				}
				break;
			}
			//每隔1秒 轮询一次
			sleep(1);
		}
	}
	return 0;
}

在这里插入图片描述

定时器信号

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
参数:秒数
当定时器指定的时间到了时,它就向进程发送SIGALARM信号,信号的默认操作是结束进程.
注意:每个进程只能有一个闹钟时间。如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,则该闹钟时间的剩余时间值作为本次alarm函数调用的值返回,以前登记的闹钟时间则被新值代换。如果有以前登记的尚未超过的闹钟时间,而新设的闹钟时间值为0,则取消以前的闹钟时间,其剩余时间值仍作为函数的返回值。
扩充:将调用进程挂起函数:
#include <unistd.h>
int pause(void);
功能:会造成进程主动挂起(处于阻塞状态,并主动放弃CPU),并且等待信号将其唤醒

案例:使用alarm()和pause()函数

#include <stdio.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	printf("hello!\n");
	//设定闹钟 5秒
	alarm(5);
	printf("I will.....\n");
	//进程挂起
	pause();
	printf("java!\n");
	printf("exit!\n");
	return 0;
}

在这里插入图片描述

响应信号

在这里插入图片描述
在这里插入图片描述

信号安装:

signal函数原型:
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
优化原型:看的更清楚。
//给函数指针类型取别名
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

功能:进行信号安装
参数:
参数1:需要安装的信号名称
参数2:对于该信号的处理函数(该函数是用户自定义的,且返回值类型void ,形参是一个
int的函数的地址)
PS:参数2的位置可以传入:忽略(SIG_IGN) 执行缺省操作(SIG_DFL),信号处理函数的地址
返回值:成功安装完毕的信号处理函数的地址。

信号的处理方式可以有:
1、忽略信号
2、执行缺省操作(默认操作)
3、捕捉信号(自定义信号处理函数)

忽略信号
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	//安装信号
	signal(SIGINT, SIG_IGN);//忽略信号
	//执行一段代码
	while(1)
	{
		printf("hello!\n");
		sleep(1);
	}
	return 0;
}

在这里插入图片描述

执行缺省操作
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	//安装信号
	//signal(SIGINT, SIG_IGN);//忽略信号
	signal(SIGINT, SIG_DFL);//缺省操作(信号默认处理方式)
	//执行一段代码
	while(1)
	{
		printf("hello!\n");
		sleep(1);
	}
	return 0;
}

在这里插入图片描述

捕捉信号
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler_func(int signum)
{
	printf("不处理哦!\n");
}
int main(int argc, const char *argv[])
{
	//安装信号
	//signal(SIGINT, SIG_IGN);//忽略信号
	//signal(SIGINT, SIG_DFL);//缺省操作(信号默认处理方式)
	signal(SIGINT, &handler_func);
	//执行一段代码
	vwhile(1)
	{
		printf("hello!\n");
		sleep(1);
	}
	return 0;
}

在这里插入图片描述
注意:一个信号处理函数响应多个信号

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void handler_func(int signum)
{
	//按照信号的类别进行控制
	switch(signum)
	{
		case SIGINT:
		{
			printf("paly music...\n");
			break;
		}
		case SIGTSTP:
		{
			printf("paly vedio...\n");
			break;
		}
		case SIGQUIT:
		{
			printf("quit...\n");
			break;
		}
		default:
		{
			printf("信号无法响应...\n");
		}
	}
	return;
}
int main(int argc, const char *argv[])
{
	//安装信号
	//signal(SIGINT, SIG_IGN);//忽略信号
	//signal(SIGINT, SIG_DFL);//缺省操作(信号默认处理方式)
	//signal(SIGINT, &handler_func);//捕捉信号--》自定义信号处理函数
	//安装3个信号
	signal(SIGINT, &handler_func);//播放音乐
	signal(SIGTSTP, &handler_func);//播放视频
	signal(SIGQUIT, &handler_func);//退出app
	//执行一段代码
	while(1)
	{
		printf("hello!\n");
		sleep(1);
	}
	return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】概述1

非 ~ 注释 % 定义 >> 数组 赋值 赋值&#xff1a;>> x1 函数 数组 x[x1,x2] 行向量&#xff08;&#xff0c;or ) x[x1;x2] 列向量 x. 转置等间隔向量 1-10 向量&#xff1a;>>xlinspace(1,10,10) 矩阵 矩阵&#xff1a;>>A[1,2,3;4,5,6;7,8,9] …

重生之 SpringBoot3 入门保姆级学习(10、日志基础与使用)

重生之 SpringBoot3 入门保姆级学习&#xff08;10、日志基础使用&#xff09; 3.1 日志基础3.2 使用日志3.2.1 基础使用3.2.2 调整日志级别3.2.3 带参数的日志 3.1 日志基础 SpringBoot 默认使用 SLF4j&#xff08;Simple Logging Facade for Java&#xff09;和 Logback 实现…

Django ORM魔法:用Python代码召唤数据库之灵!

探索Django ORM的神奇世界&#xff0c;学习如何用Python代码代替复杂的SQL语句&#xff0c;召唤数据库之灵&#xff0c;让数据管理变得轻松又有趣。从基础概念到高级技巧&#xff0c;阿佑带你一步步成为Django ORM的魔法师&#xff0c;让你的应用开发速度飞起来&#xff01; 文…

Adobe Acrobat DC无法卸载

控制版面、电脑管家等均无法卸载&#xff0c;使用自身的remove也不能卸载 解决方法&#xff1a;删除Adobe Acrobat DC的注册表 1、首先打开注册列表&#xff1a; 2、根据圈出来的信息&#xff0c;找到以下路径&#xff1a; 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Inst…

c++车票管理系统

这里写自定义目录标题 c车票管理系统vx:sredxc车票管理系统初始页面,需要源码vx:sredxc新增车票信息查询车票信息代码包含完整的发布车票信息,购票,退票,票数检测,余票检测,车票查询等功能 c车票管理系统vx:sredxc 这段代码实现了一个简单的高铁票务管理系统&#xff0c;具有以…

动态路由OSPF单区域和多区域配置实验

动态路由OSPF的配置 OSPF分类两种情况&#xff1a;单区域 多区域路由 OSPF单区域路由配置 OSPF&#xff1a;开放最短路径优先的路由协议。属于大型动态路由协议&#xff0c;适用于中大型的园区网。 网络拓扑&#xff1a; 配置步骤&#xff1a; 1.完成基本配置&#xff08;略&…

如何在测试/线上环境页面访问本地接口?

文章目录 一、前言二、分析三、搭建1、搭建nginx&#xff0c;监听http请求转发2、监听https请求转发 四、总结 一、前言 在工作中&#xff0c;开发完的接口&#xff0c;一般测试的话&#xff0c;基本是使用Postman&#xff0c;如果要到页面测试&#xff0c;就要发版进行测试&a…

5.29工效学-人因工程人机交互

对于工效学这门课&#xff0c;一直都感觉很有意思&#xff0c;是一个值得再认真一点的课。可惜上课的时候效率不高&#xff0c;有感兴趣的东西课后也没有自行去拓展开来&#xff0c;前面的课我感觉还讲了比较重要的东西&#xff0c;但是&#xff0c;全忘了呢&#xff08;真的对…

8、资源操作 Resource

目录 8.1、Spring Resources概述补充&#xff1a;什么是 low-level 资源&#xff1f;1. 文件系统资源2. 类路径资源3. URL资源4. 内嵌资源5. InputStream资源6. ServletContext资源示例代码结论 8.2、Resource接口8.3、Resource的实现类8.3.1、UrlResource访问网络资源1&#x…

华为设备配置静态路由和默认路由

华为设备配置静态路由和默认路由 理论部分知识&#xff1a; 路由分为两个大类&#xff1a;静态路由-----动态路由 静态路由&#xff1a;手工指定&#xff0c;适用于小规模的网络应用场景&#xff0c;如果网络规模变大&#xff0c;这样的方式非常不适合而且容易出错。 语法&…

C#使用GDI对一个矩形进行任意角度旋转

C#对一个矩形进行旋转GDI绘图&#xff0c;可以指定任意角度进行旋转 我们可以认为一张图片Image&#xff0c;本质就是一个矩形Rectangle,旋转矩形也就是旋转图片 在画图密封类 System.Drawing.Graphics中&#xff0c; 矩形旋转的两个关键方法 //设置旋转的中心点 public v…

初识C++ · 模拟实现list

目录 前言 1 push_back pop_back 2 迭代器类 2.1 ! 2.2 -- 2.3 * 3 Print_List 4 有关自定义类型 5 有关const迭代器 6 拷贝构造 赋值 析构 Insert erase 前言 有了string&#xff0c;vector的基础&#xff0c;我们模拟实现list还是比较容易的&#xff0c;这里同…

基于LQR控制算法的电磁减振控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于LQR控制算法的电磁减振控制系统simulink建模与仿真。仿真输出控制器的收敛曲线。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB2022a 08_029m 4.系统原理…

XXE漏洞简介

目录 漏洞原理 漏洞危害 前置知识 XML简介 DTD简介 DTD的两种声明方式 实体 实体分类 内置实体(Built-inentities) 字符实体&#xff08;Characterentities&#xff09; 通用实体&#xff08;Generalentities&#xff09; 参数实体(Parameterentities) XXE漏洞…

算法每日一题(python,2024.05.24) day.6

题目来源&#xff08;力扣. - 力扣&#xff08;LeetCode&#xff09;&#xff0c;简单&#xff09; 解题思路&#xff1a; 排序&#xff0b;双指针 先将两个数组进行排序&#xff0c;cursor1和cursor分别指向两个数组的首位&#xff0c;比较两个指针所指的值的大小&#xff0…

iotdb时序库在火电设备锅炉场景下的实践【原创文字,IoTDB社区可进行使用与传播】

一.概述 1.1 说明 本文章主要介绍iotdb数据库在电站锅炉工业场景下&#xff0c;对辅助智能分析与预警的使用介绍。 【原创文字&#xff0c;IoTDB社区可进行使用与传播】 1.2 项目背景 随着人工智能算法在电力领域的发展&#xff0c;以及燃煤锅炉设备精细化调整需求的增加&…

Java Apache Jaccard文本相似度匹配初体验

文章目录 前言一、文本相似度算法的选择二、常见的文本相似度算法介绍三、使用示例1、引入jar包2、方法示例3、Jaccard源码剖析4、Jaccard源码解释 写在最后 前言 产品今天提了个需求&#xff0c;大概是这样的&#xff0c;来&#xff0c;请看大屏幕。。。额。。。搞错了&#…

系统思考—思考快与慢

“膝反射思考做决策&#xff0c;你的公司能走多远&#xff1f;” 在快节奏的商业环境中&#xff0c;我们的大脑往往默认采用“快速直觉反应”模式来做决策&#xff0c;这种方式节省能量&#xff0c;属于我们认知的“系统一”。然而&#xff0c;仅依靠直觉反应&#xff0c;即所…

go中的指针详解

因为大一的时候c语言没学好,所以看到指针很心烦 ,后来速成了一遍go ,每每写道指针部分就开始遗忘 ,所以专门对指针部分做了此笔记 概念 在 Go 语言中&#xff0c;指针是一种变量类型&#xff0c;它存储的是另一个变量的内存地址。通过指针&#xff0c;你可以访问和修改它指向…

数据结构——经典链表OJ(二)

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 点击主页&#xff1a;optimistic_chen和专栏&#xff1a;c语言&#xff0c; 创作不易&#xff0c;大佬们点赞鼓…