【C语言】一节课拿捏---动态内存分配

news2024/10/7 12:19:45

谢谢观看!希望以下内容帮助到了你,对你起到作用的话,可以一键三连加关注!你们的支持是我更新地动力。
因作者水平有限,有错误还请指出,多多包涵,谢谢!


目录

  • 一、 为什么要有动态内存分配
  • 二、`malloc`和`free`
    • 2.1`malloc`
    • 2.2`free`
  • 三、`calloc`和`realloc`
    • 3.1`calloc`
    • 3.2`realloc`
  • 四、 常见的动态内存的错误
    • 4.1对NULL指针的解引用操作
    • 4.2对动态开辟空间的越界访问
    • 4.3对非动态开辟内存使用`free`释放
    • 4.4 使用`free`释放一块动态开辟内存的一部分
    • 4.5对同一块动态内存多次释放
    • 4.6 动态开辟内存忘记释放(内存泄漏)
  • 五、动态内存经典笔试题分析
    • 题目1
    • 题目2
    • 题目3
    • 题目4
  • 六、柔性数组
    • 6.1 柔性数组的特点:
    • 6.2 柔性数组的使用
    • 6.3 柔性数组的优势
  • 七、总结C/C++中程序内存区域划分

一、 为什么要有动态内存分配

  我们已经掌握的内存开辟方式有:

int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间

  但是上述的开辟空间的方式有两个特点

  • 空间开辟大小是固定的。
  • 数组在申明的时候,必须指定数组的长度,数组空间一旦确定了大小不能调整但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小会根据实际情况发生变化,如果使用数组的话,可能开辟的空间太大,也可能开辟的空间不够那数组的编译时开辟空间的方式就不能满足了

  所以在C语言引入了动态内存开辟,让程序员自己可以申请和释放空间,就比较灵活了。这就需要使用到库函数来进行申请内存空间了。


  

二、mallocfree

2.1malloc

  C语言提供了一个动态内存开辟的函数:

void* malloc (size_t size);
//size表示需要申请的一块空间大小是多少,单位是字节
//void*表示返回那一块空间的起始位置的地址

  这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针

  注意事项

  • 如果开辟成功,则返回一个指向开辟好空间的指针
  • 如果开辟失败,则返回一个 NULL 指针,因此malloc的返回值⼀定要做检查。
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  • 如果参数 size0malloc的行为是标准是未定义的,取决于编译器
  • 使用函数malloc之前需要加上头文件#include<stdlib.h>

  具体使用方式

//代码一
int* p = (int*)malloc(10*sizeof(int));
char* p = (char*)malloc(10*sizeof(char));

//代码二
#include<stdio.h>
#include<stdlib.h>

int main()
{
	int* p = (int*)malloc(10*sizeof(int));
	if(p == NULL)
	{
		//空间开辟失败
		perror("malloc");//perror函数会打印出错误信息
		return 1;//1表示异常返回,在主函数main()中
	}
	//可以使用40个字节的空间了
	int i = 0;
	for(i = 0;i < 10;i++)
	{
		scanf("%d",(p+i));//scanf需要的参数是空间的地址
	}
	for(i = 0;i < 10;i++)
	{
		printf("%d ",*(p+i));
	}
	return 0;
}

  那么malloc申请的空间和数组的空间有什么区别呢?

  • 动态内存的大小是可以调整的
  • 开辟空间的位置不一样,malloc开辟的空间在堆区,数组arr开辟的空间在栈区

在这里插入图片描述

  

2.2free

  C语言提供了另外一个函数free,专门是用来做动态内存的释放和回收的,函数原型如下::

void free (void* ptr);
//ptr表示形参是指针,传递地址给它
//void *表示传递任何类型的指针都可以

  free函数用来释放动态开辟的内存

  注意事项

  • 如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。
  • 如果参数 ptrNULL指针,则函数什么事都不做。

  具体使用方式

#include<stdio.h>
#include<stdlib.h>

int main()
{
	int* p = (int*)malloc(10*sizeof(int));
	if(p == NULL)
	{
		//空间开辟失败
		perror("malloc");//perror函数会打印出错误信息
		return 1;//1表示异常返回,在主函数main()中
	}
	//可以使用40个字节的空间了
	int i = 0;
	for(i = 0;i < 10;i++)
	{
		scanf("%d",(p+i));//scanf需要的参数是空间的地址
	}
	for(i = 0;i < 10;i++)
	{
		printf("%d ",*(p+i));
	}

	free(p);//动态开辟的空间使用后要进行释放
	//释放的是指针p指向的空间,使空间归还给操作系统
	//但是p依然指向着那块空间,还保留着地址,此时p就是野指针了,所以还得对p指针赋值NULL
	p = NULL;//将NULL赋值给p,表示p是空指针
	
	return 0;
}

总结mallocfree函数最好成对使用


  

三、callocrealloc

3.1calloc

  C语言还提供了一个函数叫 calloccalloc 函数也用来动态内存分配。原型如下:

void* calloc (size_t num, size_t size);
//num表示开辟空间的个数
//size表示一个空间的大小是多少,单位是字节
//void* 表示返回所开辟空间的起始地址

  注意事项

  • 函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0
  • 与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0,其他使用方法和malloc函数一模一样。

  具体使用方式

#include<stdio.h>
#include<stdlib.h>

int main()
{
	//申请10个整型的空间
	//int* p = (int*)malloc(10*sizeof(int));
	int* p = (int*)calloc(10,sizeof(int));
	
	if(p == NULL)
	{
		//空间开辟失败
		perror("calloc");//perror函数会打印出错误信息
		return 1;//1表示异常返回,在主函数main()中
	}
	
	//可以使用40个字节的空间了
	int i = 0;
	for(i = 0;i < 10;i++)
	{
		printf("%d ",*(p+i));//结果为:0 0 0 0 0 0 0 0 0 0 
	}
	free(p);//动态开辟的空间使用后要进行释放
	//释放的是指针p指向的空间,使空间归还给操作系统
	//但是p依然指向着那块空间,还保留着地址,此时p就是野指针了,所以还得对p指针赋值NULL
	p = NULL;//将NULL赋值给p,表示p是空指针
	return 0;
}

  

3.2realloc

  函数原型如下:

void* realloc (void* ptr, size_t size);
//ptr表示要调整的内存地址
//size表示调整之后新大小
//返回值为调整之后的内存起始位置

  这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间

  具体使用方式

int main()
{
	//申请10个整型的空间
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		perror("calloc");
		return 1;
	}
	//使用空间
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);//*(p+i)
	}

	//调整空间-希望变成20个整型空间
	int* p = (int*)realloc(p, 20 * sizeof(int));
	//这里对realloc函数返回空间的起始地址传递给指针p是否正确?
	if (ptr != NULL)
	{
		p = ptr;
	}
	//使用
	//...
	
	//释放
	free(p);
	p = NULL;

	return 0;
}


//用法二:realloc不仅可以调整空间,可以开辟空间
int * p = (int *)realloc(NULL,40);
//等价于 int * p = (int*)malloc(10*sizeof(int))

  在上面的代码中的这一部分,我们怎么判断是否正确呢?这就需要了解一下,realloc函数调整内存空间的细节了

//调整空间-希望变成20个整型空间
	int* p = (int*)realloc(p, 20 * sizeof(int));
	//这里对realloc函数返回空间的起始地址传递给指针p是否正确?

  realloc在调整内存空间的是存在两种情况:

  • 情况1:原有空间之后有足够大的空间
  • 情况2:原有空间之后没有足够大的空间

  注意情况1情况2都是正常可以分配空间的情况,如果未分配成功的话,会返回NULL空指针。
在这里插入图片描述
  
  所以通过上面的细节,我们知道了假如realloc函数分配空间失败后返回NULL,然后我们将指针p去接受,会导致我们连原来已经分配好的空间都找不到了但是我们希望就算分配失败了也不应该将原来的空间都找不到。所以我们可以使用另一个指针ptr去接收它的返回值,然后再进行判断这个指针是否为NULL,如果不是NULL,则再将prt的值赋值给p

int main()
{
	//申请10个整型的空间
	int* p = (int*)calloc(10, sizeof(int));
	if (p == NULL)
	{
		perror("calloc");
		return 1;
	}
	//使用空间
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);//*(p+i)
	}

	//调整空间-希望变成20个整型空间
				//int* p = (int*)realloc(p, 20 * sizeof(int));不使用这种方式,有危险
	int* ptr = (int*)realloc(p, 20 * sizeof(int));
	//ptr不为NULL时,再赋值给p
	if (ptr != NULL)
	{
		p = ptr;
	}
	//使用
	//...
	
	//释放
	free(p);
	p = NULL;

	return 0;
}

  

四、 常见的动态内存的错误

4.1对NULL指针的解引用操作

//错误写法
void test()
 {
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//如果p的值是NULL,就会有问题
 //因为malloc函数可能会分配空间失败返回NULL,然而当对NULL空指针解引用操作*会出错
 free(p);
 p=NULL;
 }

//正确写法
void test()
 {
 	int *p = (int *)malloc(INT_MAX/4);
 	if(p == NULL)
 	{
		perror("malloc");
		return 1;
	}
 	*p = 20;
 	free(p);
 	p=NULL;
 }

4.2对动态开辟空间的越界访问

//错误写法
void test()
 {
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<40; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
 }

//正确写法
void test()
 {
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<10; i++)
 {
 *(p+i) = i;//当i是10的时候越界访问
 }
 free(p);
 }

4.3对非动态开辟内存使用free释放

//错误写法
void test()
{
 int a = 10;
 int *p = &a;
 free(p);//ok?
 //free只能对动态内存处理
 }

4.4 使用free释放一块动态开辟内存的一部分

//错误写法
void test()
 {
 int *p = (int *)malloc(100);
 p++;//此时的p指针并不是指向了动态内存分配的起始地址,而是跳过了4个字节的空间
 free(p);//p不再指向动态内存的起始位置
 }

4.5对同一块动态内存多次释放

//错误写法
void test()
 {
 int *p = (int *)malloc(100);
 free(p);
 free(p);//重复释放,相当于对p野指针进行了释放,这是不允许的
 }

//正确写法
void test()
 {
 int *p = (int *)malloc(100);
 //...
 free(p);
 p=NULL;

//...
 free(p);
 p=NULL;
 }

4.6 动态开辟内存忘记释放(内存泄漏)

void test()
 {
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }
 }
int main()
 {
 test();
 while(1);
 }

  


五、动态内存经典笔试题分析

题目1

//错误写法
void GetMemory(char *p)//p是str的临时拷贝
 {
 p = (char *)malloc(100);//后面没有free释放,导致内存泄漏
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(str);
 strcpy(str, "hello world");//str还是空指针,导致了对NULL指针解引用操作,程序崩溃
 //要知道strcpy的实现
 printf(str);//这样的写法没有错,是对的,类型于printf("hehe\n"),"hehe\n"是常量字符串,值是首字符的地址
 }


//正确写法
//写法一
void GetMemory(char **p)
 {
 *p = (char *)malloc(100);
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(&str);
 strcpy(str, "hello world");
 printf(str);
 free(str)
 str = NULL;
 }
//写法二
void GetMemory()
 {
 char * p = (char *)malloc(100);
 return p;
 }
void Test(void)
 {
 char *str = NULL;
 str =GetMemory();
 strcpy(str, "hello world");
 printf(str);
 free(str)
 str = NULL;
 }

题目2

char *GetMemory(void)
{
 char p[] = "hello world";//当出了该函数,数组是局部变量,有作用域,空间中的数据会被销毁
 return p;
}
void Test(void)
{
 char *str = NULL;
 str = GetMemory();
 //虽然str指针接收了字符数组的首元素地址,指向了原来的字符数组空间,但是那空间已经归还操作系统了,不在属于这个程序了
 //str是野指针了
 printf(str);
}

  注意:题目2就是典型的错误返回栈空间地址的问题。

题目3

//错误写法
void GetMemory(char **p, int num)
 {
 *p = (char *)malloc(num);
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);//结果可以打印出hello,但是不使用后,要将动态申请的内存空间给释放掉,
 //所以导致内存泄漏
 }

//正确写法
void GetMemory(char **p, int num)
 {
 *p = (char *)malloc(num);
 }
void Test(void)
 {
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
 free(str);
 str = NULL;
 }

题目4

//错误写法
void Test(void)
 {
 	char *str = (char *) malloc(100);
 	strcpy(str, "hello");
 	free(str);//此时str是野指针,但是str还是指向原来的空间
 	if(str != NULL)
 	{
 		strcpy(str, "world");//strcpy函数中年会对野指针str进行了解引用操作,非法访问
 		printf(str);
 	}
 }

//正确写法
void Test(void)
 {
 	char *str = (char *) malloc(100);
 	strcpy(str, "hello");
 	free(str);
 	str = NULL;
 	if(str != NULL)
 	{
 		strcpy(str, "world");
 		printf(str);
 	}
 }

  


六、柔性数组

  也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

struct S
{
	int n;
	char c;
	double d;
	int arr[];//未知大小的数组 - arr就是柔性数组的成员
	//也可以写成int arr[0]
};

6.1 柔性数组的特点:

  • 结构中的柔性数组成员前面必须至少一个其他成员。
  • sizeof 返回的这种结构大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
struct S
{
	int n;
 	int arr[0];//柔性数组成员
};
int main()
{
 	printf("%d\n", sizeof(struct S));//输出的是4
 	return 0;
}

6.2 柔性数组的使用

struct S
{
	int n;
 	int arr[];//柔性数组成员
};
int main()
{
 	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20*sizeof(int));
 	//20*sizeof(int)是为arr数组动态分配的,表示数组arr有20个整型
 	if(ps == NULL)
 	{
		perror("malloc()");
		return 1;
	}

	//使用空间
	ps->n=100;
	int i = 0;
	for(i = 0; i < 20 ; i++)
	{
		ps->arr[i] = i + 1;
	}

	//调整ps指向空间的大小
	struct S* ptr = (struct S*)realloc(ps,sizeof(struct S) + 40 * sizeof(int));
	if(ps != NULL)
	{
		ps = ptr;
		ptr = NULL;//防止ptr为野指针
	}
	else
	{
		return 1;
	}

	//使用空间
	for(i = 0 ; i < 40 ; i++)
	{
		printf("%d ",ps->arr[i]);
	}

	//释放空间
	free(ps);
	ps = NULL;
	
 	return 0;
}

6.3 柔性数组的优势

//代码一
struct S
{
	int n;
	int* arr;
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	int*tmp = (int*)malloc(20*sizeof(int));
	if (tmp != NULL)
	{
		ps->arr = tmp;
	}
	else
	{
		return 1;
	}
	ps->n = 100;
	int i = 0;
	//给arr中的20个元素赋值为1~20
	for (i = 0; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}
	//调整空间
	tmp = (int*)realloc(ps->arr, 40*sizeof(int));
	if (tmp != NULL)
	{
		ps->arr = tmp;
	}
	else
	{
		perror("realloc");
		return 1;
	}
	//
	for (i = 0; i < 40; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	//释放
	free(ps->arr);//先释放第二次申请的空间
	ps->arr = NULL;

	free(ps);//再释放第一次申请的空间
	ps = NULL;

	return 0;
}
//代码二
struct S
{
	int n;//4
	int arr[];
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20*sizeof(int));
	if(ps == NULL)
	{
		perror("malloc()");
		return 1;
	}
	//使用这些空间
	ps->n = 100;
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		ps->arr[i] = i + 1;
	}

	//调整ps指向空间的大小
	struct S* ptr = (struct S*)realloc(ps, sizeof(struct S) + 40 * sizeof(int));
	if (ptr != NULL) 
	{
		ps = ptr;
		ptr = NULL;
	}
	else
	{
		return 1;
	}
	//使用
	for (i = 0; i < 40; i++)
	{
		printf("%d ", ps->arr[i]);
	}

	//释放空间
	free(ps);
	ps = NULL;

	return 0;
}

  
  上述 代码一代码二 可以完成同样的功能,但是 代码二 的实现有两个好处
在这里插入图片描述

  


七、总结C/C++中程序内存区域划分

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

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

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

相关文章

关于IDEA创建Maven一直爆红无法下载的问题

你能看到这我就知道你肯定已经试过了网上的很多方法了&#xff0c;我之前也是&#xff0c;试过了很多一直无法正常下载&#xff0c;我也是找人给 线下看了看解决了&#xff0c;我总结一下从头到尾排除问题&#xff0c;试到最后要是还解决不了你直接私信我&#xff0c;我给你看看…

vue3+uniapp

1.页面滚动 2.图片懒加载 3.安全区域 4.返回顶部&#xff0c;刷新页面 5.grid布局 place-self: center; 6.模糊效果 7.缩放 8.微信小程序联系客服 9.拨打电话 10.穿透 11.盒子宽度 12.一般文字以及盒子阴影 13.选中文字 14.顶部安全距离 15.onLoad周期函数在setup语法糖执行后…

微信小程序-案例:本地生活-首页(不使用网络数据请求)

一、 1.页面效果&#xff1a; 二、 1.新建项目并添加页面 在app.json文件中&#xff1a; "pages": ["pages/home/home","pages/message/message","pages/contact/contact"] 2.配置导航栏效果 在app.json文件中&#xff1a; &quo…

DVWA-XSS(DOM)

Low 后端没有代码&#xff0c;点击select按钮动作是前端的JS代码进行处理的 function addEventListeners() {var source_button document.getElementById ("source_button");if (source_button) {source_button.addEventListener("click", function() {v…

Doris Connector 结合 Flink CDC 实现 MySQL 分库分表

1. 概述 在实际业务系统中为了解决单表数据量大带来的各种问题&#xff0c;我们通常采用分库分表的方式对库表进行拆分&#xff0c;以达到提高系统的吞吐量。 但是这样给后面数据分析带来了麻烦&#xff0c;这个时候我们通常试将业务数据库的分库分表同步到数据仓库时&#x…

【杂谈】AIGC之ChatGPT-与智能对话机器人的奇妙对话之旅

与智能对话机器人的奇妙对话之旅 引言 在数字时代的浪潮中&#xff0c;ChatGPT如同一位智慧的旅伴&#xff0c;它不仅能够与我们畅谈古今&#xff0c;还能解答我们的疑惑&#xff0c;成为我们探索知识海洋的得力助手。今天&#xff0c;就让我们走进ChatGPT的世界&#xff0c;…

Capture One Pro 23:专业 Raw 图像处理的卓越之选

在当今的数字摄影时代&#xff0c;拥有一款强大的图像处理软件至关重要。而 Capture One Pro 23 for Mac/Win 无疑是其中的佼佼者&#xff0c;为摄影师和图像爱好者带来了前所未有的体验。 Capture One Pro 23 以其出色的 Raw 图像处理能力而闻名。它能够精准地解析和处理各种…

题号:BC19 题目:反向输出一个四位数

题号&#xff1a;BC19 题目&#xff1a;反向输出一个四位数 废话不多说&#xff0c;上题目&#xff1a; 解题思路&#xff1a; 我们发现可以用%和/两个操作符就可以解决。 代码如下: int main() {int a 0;scanf("%d ",& a);while (a){printf("%d "…

基于googlenet深度学习网络的睁眼闭眼识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................................................................. % 对测试集进行分类预…

如何通过 6 种简单方法将照片从华为转移到 PC?

华为作为全球领先的智能手机供应商之一&#xff0c;最近推出了其自主研发的操作系统——HarmonyOS 2.0&#xff0c;旨在为智能手机、平板电脑和智能手表等设备提供更流畅的用户体验。随着Mate 40/P40等系列手机计划升级到HarmonyOS 2.0&#xff0c;用户可能需要将手机中的文件备…

Aws EC2,kubeadm方式安装kubernetes(k8s)

版本 docker版本&#xff1a;20.10.25 k8s版本&#xff08;kubeadm&#xff0c;kubelet和kubectl&#xff09;&#xff1a;1.20.10-0 初始化 # 禁用 SELinux sudo setenforce 0 sudo sed -i s/^SELINUXenforcing$/SELINUXpermissive/ /etc/selinux/config# 关闭防火墙 sudo …

计算机网络—路由器综合实验

一、实验内容 利用1个三层交换机和2个路由器完成以下实验&#xff1a; 1、路由器的基本配置 2、三层交换机的基本配置及路由配置 3、路由协议 &#xff08;动态路由RIPv2&#xff09; 二、实验环境与设备 &#xff08;一&#xff09;实验环境 Cisco Packet Tracer 8.2.1 &am…

1V1音视频实时互动直播系统

李超老师的项目 先肯定分为两个两个端&#xff0c;一个是服务器端一个是客户端。客户端用于UI界面的显示&#xff0c;服务器端用于处理客户端发来的消息。 我们先搭建stun和turn服务器 首先介绍一下什么是stun协议&#xff0c; 它是用来干什么的&#xff1f; stun协议存在…

有没有全面的人、货、场零售数据分析方案?

有。奥威BI零售数据分析方案正是这样一套全面的人、货、场零售数据分析解决方案&#xff0c;旨在帮助零售企业实现数据驱动的决策&#xff0c;优化业务流程&#xff0c;提升市场竞争力。 一、方案概述 该零售数据分析方案基于先进的BI技术&#xff0c;预设了以人、货、场、供…

Ubuntu安装cuda

文章目录 前言一、安装NVIDIA驱动1.1 过程中的问题1.2 解决方法1.3 重启后出现 perform MOK management 二、安装Cuda2.1 检查是否安装显卡驱动2.2 安装Cuda2.3 验证CUDA是否安装成功 三、配置环境变量---未完2.4 图片居中加调整大学 总结 #pic_center 前言 只是为方便学习&…

【设计模式深度剖析】【2】【行为型】【命令模式】| 以打开文件按钮、宏命令、图形移动与撤销为例加深理解

&#x1f448;️上一篇:模板方法模式 设计模式-专栏&#x1f448;️ 文章目录 命令模式定义英文原话直译如何理解呢&#xff1f; 四个角色1. Command&#xff08;命令接口&#xff09;2. ConcreteCommand&#xff08;具体命令类&#xff09;3. Client&#xff08;客户端&…

Linux驱动开发笔记(六)中断子系统及实验

文章目录 前言一、中断子系统框架1. 中断硬件简单描述2. 中断的软件描述2.1 中断处理的两部分模型2.2 系统框架 二、GIC v3中断控制器1. GIC v3基本结构1.1 Distributor1.2 Redistributor1.3 ITS1.4 CPU interface 2. 中断类型与特点3. 中断号 三、函数编写3.1 相关API函数3.2 …

【自动驾驶】针对低速无人车的线控底盘技术

目录 术语定义 一般要求 操纵装置 防护等级 识别代号 技术要求 通过性要求 直线行驶稳定性 环境适应性要求 功能安全要求 信息安全要求 故障处理要求 通信接口 在线升级(OTA) 线控驱动 动力性能 驱动控制响应能力 线控制动 行车制动 制动响应能力 线控转向 总体要求 线控…

计算机网络 期末复习(谢希仁版本)第5章

**屏蔽作用&#xff1a;**运输层向高层用户屏蔽了下面网络核心的细节&#xff08;如网络拓扑、所采用的路由选择协议等&#xff09;&#xff0c;使应用进程看见的就是好像在两个运输层实体之间有一条端到端的逻辑通信信道。 10. 端口用一个 16 位端口号进行标志&#xff0c;允许…

力扣 496. 下一个更大元素 I

题目来源&#xff1a;https://leetcode.cn/problems/next-greater-element-i/description/ C题解1&#xff1a;暴力解决 class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {int len1 nums1.size(…