C语言:自定义类型 - 结构体 联合体 枚举

news2024/11/18 17:50:44

C语言:自定义类型 - 结构体 & 联合体 & 枚举

    • 结构体
      • 结构体声明
      • 结构体创建
        • 匿名结构体
        • 初始化
      • 结构体的重命名
      • 结构体访问
      • 内存对齐
      • 位段
    • 联合体
    • 枚举


在C语言中,自定义类型是指程序员可以通过一系列的定义和说明来创建的新的数据类型。这些自定义类型可以是基本类型的组合或者是基于现有类型的扩展。包括数组在内,C语言的自定义类型有:数组结构体联合体枚举


结构体

结构体是一些不同类型值的集合,这些值称为成员变量

结构体声明

基本语法:

struct name
{
	member-list;
};   //此处有分号

struct:结构体关键字,用于声明结构体
name:结构体名称
member - list:成员列表

比如描述一个学生:

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}; 

此时这个结构体Stu内部就有四个变量nameagesexid,它们称为成员变量


结构体创建

结构体是一种类型,类型就是用来创建变量的,那么我们要如何通过这个自定义的类型来创建变量?

Stu结构体为例:

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
}; 

此结构体的名称为Stu,其类型为struct Stu,也就是说结构体的类型是struct关键字 + 名称

直接创建
我们创建一个整型变量为int a;,也就是类型 + 变量名。而结构体的类型为struct + 名称,所以创建Stu的变量语法为:

struct Stu a;

再比如创建该结构体的指针:

struct Stu* pa;

该结构体的数组:

struct Stu arr[10];

声明时创建
结构体是可以在声明的同时创建变量的,只需要将变量写在结构体末尾的} ;之间。

比如创建一个a变量:

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
}a; //此处创建了a变量

如果需要创建多个变量,那就用逗号分开:

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
}a, *p, arr[10];

此处创建了三个变量,分别是结构体a,该结构体的指针p,该结构体的数组arr
注意:通过这种方式创建的变量为全局变量


匿名结构体

结构体在声明时,其实名字是可以省略的,这种结构体叫匿名结构体。
匿名结构体必须在声明时定义变量。因为匿名结构体没有名称,后续无法通过这个匿名结构体的类型来定义变量,所以必须在声明时定义变量。

示例:

struct
{
	int a;
	double b;
	char c;
}x;

上述代码就是一个匿名结构体,它在struct关键字后面没有名称,但是在声明时定义了一个变量x。后续我们可以使用这个x,但是无法创建一个与x相同类型的变量了。

看到一下代码:

struct
{
	double b;
	char c;
}x1;

struct
{
	double b;
	char c;
}x2;

请问:x1x2是同一类型吗?
此处定义了两个匿名结构体,它们的成员变量完全一致,但是它们并不是同一种类型的变量。

匿名结构体之间,哪怕成员变量完全一致,也是两个不同类型的结构体


初始化

结构体的初始化分为两种:按照顺序,不按照顺序。

按照顺序初始化

struct Stu a = {"zhangsan", 20, "男", "2023200512225"};

以上代码,将Stu结构体中的name = "zhangsan"age = 20sex = “男”id = "202320051225"。这就是按照顺序直接初始化,赋值也是如此。

不按照顺序初始化

struct Stu a = { .age = 20, .id = "2023200512225", .name = "zhangsan",.sex = "男" };

如果不按照顺序,那么就要指定每一个成员的值是谁,注意成员名前面有一个.

在声明时创建同理:

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
}a = {"zhangsan", 20, "男", "2023200512225"};

结构体的重命名

结构体可以使用typedef进行重命名,但是其有不一样的语法规则。

一般形式

struct A
{
	double b;
	char c;
};

typedef struct A sA;

最后一个typedef就是我们的结构体重命名,这是符合一般的typedef重命名规则的,此处将struct A重命名为了sA

很多时候我们会这样做:

typedef struct A A;

很多人也许会疑惑:为什么要把结构体A重命名为A
首先,此处重命名的不是A,而是struct A
其次,这么做的意义是:我们平时利用结构体定义变量时要用struct A xxx;,而typedefA后,就可以A xxx;这样创建变量,可以少写一个struct 关键字,所以很常用。

声明时重命名
结构体还有特殊的重命名语法:在声明时重命名

typedef struct A
{
	double b;
	char c;
}sA;

typedef写在struct的前面,将新名称sA写在};之间。
其效果和typedef struct A sA;一致。


结构体访问

访问结构体变量的成员,有两种方式:通过变量访问通过指针访问

通过变量访问
结构体成员访问操作符.,可以访问到一个结构体成员变量。

依然以Stu结构体为例:

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
};

访问:

struct Stu s = {"zhangsan", 20, "男", "2023200512225"};

char* c = s.name;
int a = s.age;
s.id = "202420101001";

以上示例中,我们通过.访问了三个成员变量,s.name访问了name成员,并它的值赋给cs.id则是访问了id成员,并把它的值改为"202420101001"

通过指针访问
有的时候我们会得到结构体的指针,此时就要解引用后访问:

struct Stu s = {"zhangsan", 20, "男", "2023200512225"};
struct Stu* ps = &s;

此时我们得到了一个结构体指针ps,接下来我们尝试访问:

*ps.name = "lisi";

首先我们解引用了指针*ps,然后通过结构体访问操作符.访问了name成员。但是这个写法是错误的,因为*的优先级比.,其会先通过ps访问ps.name,这就会发生错误,所以我们要用小括号()调整执行顺序,像这样:

*(ps).name = "lisi";

这样访问实在是太别扭了,C语言还有另外一种通过指针访问结构体成员的方式,另外一个结构体成员访问操作符->。其可以通过指针访问结构体:

ps->name = "lisi";
ps->age = 18;

这样就方便很多了。


内存对齐

请问以下结构体占用的内存是多大:

struct S1
{
	char c1;
	int i;
	char c2;
};

经过粗略计算,我们得到char + int + char = 1 + 4 + 1 = 6,即6字节,我们试验一下看看:

printf("%d", sizeof(S1));

输出结果:12(vs2022环境下,其它编译器有可能得到不同结果)
这就奇怪了,为啥是12啊?这就涉及到结构体特殊的内存对齐规则了。

内存对齐规则:

  1. 结构体的第⼀个成员对⻬到相对结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对⻬到对⻬数的整数倍的地址处。
  3. 结构体总⼤⼩为最⼤对⻬数的整数倍
  4. 如果嵌套了结构体的情况,嵌套的内层结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,外层结构体的最⼤对⻬数就是内外层结构体中所有成员的最大对⻬数

这套规则光看文字比较晦涩,还是需要结合案例讲解,我们一条一条拆分出来:

现在有如下内存,左侧的数值为相对地址:
在这里插入图片描述

假设我们要在这里面存放结构体:

struct S1
{
	char c1;
	int i;
	char c2;
};

规则1:第一个成员变量对齐到起始位置偏移量为0的地方,由于第一个成员是char类型,所以占一个字节,当前内存分布如下:
在这里插入图片描述
随后我们放置第二个变量i
规则2:其它成员变量对齐到对齐数的整数倍的地址处
什么是对齐数?对齐数就是一个数值,其会限制一个成员的对齐规则。而不同编译器有自己的默认对齐数,在vs2022中,默认对齐数为8在Linux中,没有默认对齐数

成员对齐数 = 该成员的大小 与 默认对齐数的较小值

比如在当前的vs2022环境下,成员变量i的类型是int类型,其大小为4字节,而vs2022的默认对齐数为8字节,最后i的对齐数 = min(4, 8),也就是4。

现在我们得到了i的对齐数,现在就应该内存对齐了,再看一遍规则2:其它成员变量对齐到对齐数的整数倍的地址处。也就是是说,我们的i要落在4的倍数处。当前C1只占用了一个内存,下一个是4的倍数的地址就是4地址i对齐到此处,而i占用四个字节,现在内存分布如下:

在这里插入图片描述

然后是最后一个变量C2的位置,首先根据规则2,其对齐数为char类型大小1以及默认对齐数8的较小值,即1。所以C2要对齐到1的倍数处。下一个1的倍数就是8内存处,而C2占用1字节,现在内存分配如下:

在这里插入图片描述
现在我们知道三个成员分别是如何对齐的了,那么结构体最后是多大呢?
三个成员对齐后,加起来共占用了9块内存,那么内存是9吗?
并不是的,这就要看到规则3:结构体的总大小为最大对齐数的整数倍

我们回忆一下三个变量的对齐数:C1C2的对齐数为1;i的对齐数为4。那么整个结构体的最大对齐数就是4所以结构体的总大小必须是4的倍数,而下一个4的倍数为12,所以结构体的总大小为12

最后结构体视图如下:
在这里插入图片描述
接着我们还要考虑一下结构体嵌套的问题:

现有如下结构体,求其内存大小:

struct S3
{
	double d1;
	char c1;
	int i;
};

struct S4
{
	char c2;
	struct S3 s;
	double d2;
};

对于S3这个结构体,我们前三条规则就可以解决,现在你可以暂停思考一下,然后与给出的结果比对:
在这里插入图片描述

对齐数为:d = 8c = 1i = 4
最大对齐数为:8
总内存大小为:16

接下来我们讨论嵌套了S3S4

struct S4
{
	char c2;
	struct S3 s;
	double d2;
};

首先对于C2,对齐数为2,对齐到0处:
在这里插入图片描述
接着就是被嵌套的S3
规则4前半段:如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的最⼤对⻬数的整数倍处

S3的最大对齐数为8,所以S3对齐到8的整数倍处,占用16哥字节,现在内存视图如下:
在这里插入图片描述
最后是d2,其大小为8,默认对齐数为8,最后对齐数为8。要对齐到8的整数倍处。我们先前嵌套了S3,其内存大小为16,也就是说i变量下面的一块内存24也是属于S3的,因为S3的内存是8的倍数,所以多补了一块内存。但是当这个S3被嵌套到这个S4中,为其补充的总内存就不作数了,此时24并不属于S3
所以d2会对齐到下一个8的倍数24处,现在内存视图如下:

在这里插入图片描述
那么S4的总大小是多少?那就要问S4的最大对齐数是多少?
当结构体发生嵌套,那么最大对齐数的计算法则略有改变,规则4后半段:外层结构体的最⼤对⻬数就是内外层结构体中所有成员的最大对⻬数

也就是说S4的最大对齐数是所有成员:C2DCid2中对齐数的最大值。最后为8,所以S4的大小为8的倍数,当前大小为31,最后总大小就是32。

内存对齐的意义
内存对齐会浪费这么多空间,为啥还要内存对齐呢?目前大部分资料给出以下两个原因:

平台原因
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

性能原因
数据结构(尤其是栈)应该尽可能地在⾃然边界上对⻬。原因在于,为了访问未对⻬的内存,处理器需要作两次内存访问;⽽对⻬的内存访问仅需要⼀次访问。

比如这样:

在这里插入图片描述
左侧蓝色框是一个char类型数据,右侧蓝色框是一个double数据,如果没有内存对齐,那么其状态如上,一个红色框代表8个字节。
计算机只能一次读取整个红色框的内容,如果没有内存对齐,为了读取这个double,处理器要把两个红色区域都读取,然后再把数据合并。这就会造成额外的计算开销。

内存对齐后:
在这里插入图片描述
由于double对齐到了8的倍数,此时刚刚好与内存读取的范围重合,只需要直接读取第二个红色区域即可得到数据,因此内存对齐可以提高访问效率。


offsetof
offsetof是一个宏,其可以检测到一个成员相对与结构体起始位置的偏移量。使用前需要包含头文件<stddef.h>

如下结构体:

struct S1
{
	char c1;
	int i;
	char c2;
};

使用offsetof

offsetof(S1, c1);//0
offsetof(S1, i);//4

设置对齐数
我们也可以自己设定默认对齐数,语法为:

#pragma pack(1)

以上代码就把默认对齐数设置为1了。

我们也可以设置后还原:

#pragma pack()

pack()内什么都不填,默认对齐数就会还原为默认值。


位段

C语言的结构体位段是一种用于控制结构体成员位数的特殊数据类型。它允许程序员指定结构体中每个成员变量所占的bit位数

结构体位段的定义语法如下:

struct struct_name
{
    type member_name : width;
};

其中,struct_name 是结构体的名称,member_name 是结构体中的成员变量名称,type 是成员变量的数据类型,width 是成员变量占用的bit位数。

使用结构体位段可以精确地控制结构体成员的位数,这对于节约内存空间是非常有用的。例如,如果某个成员变量的取值范围只有 0 到 3,那么可以用 2 位二进制数来表示,而不必使用整个字节来存储。

下面是一个使用结构体位段的示例:

#include <stdio.h>

struct Bits
{
    unsigned int a : 2;
    unsigned int b : 3;
    unsigned int c : 7;
};

int main()
{
    struct Bits bits;

    bits.a = 2;
    bits.b = 6;
    bits.c = 63;

    printf("a: %u\n", bits.a);
    printf("b: %u\n", bits.b);
    printf("c: %u\n", bits.c);

    printf("Size of struct Bits: %zu bytes\n", sizeof(struct Bits));

    return 0;
}

在这个示例中,结构体 Bits 中的成员变量 a 占用 2bit 位,b 占用 3bit 位,c 占用 7 bit位。程序输出如下:

a: 2
b: 6
c: 63
Size of struct Bits: 2 bytes

可以看到,成员变量 a、b、c 的取值范围会受到位数限制。另外,结构体 Bits 的大小为 2 字节,这是因为结构体中的成员变量在内存中按照对齐规则进行存储。

需要注意的是,结构体位段的位数必须小于或等于其数据类型的位数=。例如,对于 unsigned int 类型的成员变量,位数不能超过 32(32 位系统)或 64(64 位系统)。

结构体位段的位数可以是常量表达式,也可以是具体的整数值。如果位数是 0,则表示该成员变量不占用任何位,即没有实际的存储空间。

结构体位段在嵌入式系统和底层编程中经常使用,用于对硬件寄存器进行位级操作。但需要注意的是,结构体位段的行为在不同的编译器和体系结构下可能会有差异,可移植性非常差,因此在使用时应谨慎考虑兼容性问题。


联合体

联合体(union)是C语言中的一种特殊的数据类型,它允许在同一内存空间中存储不同类型的数据。联合体中的成员共享同一块内存空间,但在任意时刻只能存储其中的一个成员。它的定义形式如下:

union union_name
{
    member1_type member1_name;
    member2_type member2_name;
    ...
};

联合体由关键字union定义,其中,union_name是联合体的名称,memberX_type是成员的类型,memberX_name是成员的名称。联合体的大小与它最大的成员的大小相同。

联合体的使用方式与结构体类似,可以通过.运算符访问成员。不同之处在于联合体中的成员共享同一块内存,因此对某个成员的修改会影响到其他成员。

比如以下联合体:

union Un
{
	char c;
	int i;
};

其内存视图如下:
在这里插入图片描述
ic共用了一块空间。

下面是一个使用联合体的示例:

#include <stdio.h>

union myUnion 
{
    int i;
    float f;
    char c;
};

int main() {
    union myUnion u;
    
    u.i = 10;
    printf("i: %d\n", u.i);
    
    u.f = 3.14;
    printf("f: %.2f\n", u.f);
    printf("i: %d\n", u.i);
    
    u.c = 'A';
    printf("c: %c\n", u.c);
    printf("i: %d\n", u.i);
    printf("f: %.2f\n", u.f);
    
    return 0;
}

输出结果:

i: 10
f: 3.14
i: 1078523331
c: A
i: 65
f: 2.96

在上面的示例中,我们定义了一个联合体myUnion,它包含一个int类型的成员i、一个float类型的成员f和一个char类型的成员c。在main函数中,我们声明了一个myUnion类型的变量u

首先,我们将ui成员赋值为10,并打印出来。然后,我们将uf成员赋值为3.14,并再次打印出来。可以看到,ui成员的值发生了变化,这是因为if共享同一块内存空间。

接着,我们将uc成员赋值为字符’A’,并打印出来。同样地,uif成员的值也发生了变化,这是因为cif共享同一块内存空间。

需要注意的是,联合体的成员不要同时使用,即不要在同一时间对不同成员进行操作,除非你知道这样做的结果和意义。因为不同类型的成员可能占用不同数量的字节,同时访问可能会导致数据的错误解释。

总结一下,联合体是一种特殊的数据类型,可以在同一内存空间中存储不同类型的数据。通过共享内存空间,联合体能够节省内存,但需要注意成员的正确访问顺序和数据类型的正确解释。


枚举

在C语言中,枚举(enumeration)是一种用户定义的数据类型,用于定义一组具有离散取值的常量。枚举常量的取值范围是预先定义好的,且仅限于枚举定义中列举的值。

枚举的定义使用关键字enum,其语法如下:

enum 枚举类型名
{
    枚举常量1,
    枚举常量2,
    ...
};

其中,枚举类型名是用于声明枚举变量的标识符,可选的枚举常量是该枚举类型的取值。每个枚举常量都由标识符和可选的初始值组成,多个枚举常量之间使用逗号分隔,之前的结构体与联合体则通过分号分隔。

例如,我们可以定义一个表示星期的枚举类型:

enum Weekday
{
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

在上述示例中,枚举类型名是Weekday,枚举常量分别是MondayTuesday等,且Monday的初始值是1,其后的枚举常量没有指定初始值,它们的初始值会自动递增

定义了枚举类型后,我们可以声明该类型的变量并赋值。枚举变量的赋值只能使用枚举常量或整型常量,例如:

enum Weekday today = Wednesday;
enum Weekday tomorrow = today + 1;

枚举类型的常用操作包括比较和遍历。可以使用==运算符比较两个枚举变量的值是否相等,也可根据枚举变量的取值进行相应的逻辑判断。

总结起来,C语言中的枚举提供了一种方便的方式,用于定义一组相关的常量,提高代码的可读性和可维护性。在实际应用中,枚举常常用于表示状态、选项或标志等有限的取值。


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

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

相关文章

NPN型三极管与PNP型三极管基本原理

NPN型三极管与PNP型三极管基本原理 文章目录 NPN型三极管与PNP型三极管基本原理一、三极管二、结构三、工作原理四、基本应用五、总计 一、三极管 三极管是电子电路中最基本、最常见、重要的器件&#xff0c;其主要功能是对电流的放大和开关作用&#xff0c;从半导体结构上可以…

PostgreSQL从入门到精通教程 - 第45讲:poc-tpcc测试

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第45讲&#…

共同应对共享挑战:2023 Open Source Congress 报告(中文版)

开源社受邀参加了 2023 年 7 月底在瑞士日内瓦举办的 2023 Open Source Congress&#xff0c;并发布了一篇会议速览&#xff1b;之后 LFAPAC 发布了会议总结报告&#xff08;英文版&#xff09;&#xff0c;开源社国际接轨工作组的翻译志愿者们群策群力地翻译了该总结报告。 【…

10-Linux部署ElasticSearch

Linux部署ElasticSearch 简介 全文搜索属于最常见的需求&#xff0c;开源的 Elasticsearch &#xff08;以下简称 es&#xff09;是目前全文搜索引擎的首选。 它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。 Elasticsearch简称es&…

本地写的Bash脚本,Linux端运行报错:/bin/bash^M: bad interpreter: No such file or directory

背景 在本地写了个Bash Shell脚本&#xff0c;但上传到Linux端后加完权限执行时报错&#xff1a; &#xff08;脚本名&#xff1a;script.sh&#xff09; -bash: ./script.sh: /bin/bash^M: bad interpreter: No such file or directory 分析 这个错误通常是由于脚本文件的行…

【kubernetes】关于云原生之k8s集群中pod的容器资源限制和三种探针

目录 一、关于pod容器的资源限制 1.1资源限制的单位 CPU 资源单位 内存 资源单位 二、关于QOS服务质量&#xff08;pod的调度和驱逐有限制&#xff09; 2.1QoS服务质量分类 guaranteed验证 burstable验证 besteffort验证 2.2驱逐顺序 三、关于pod容器的三种探针 3.…

【数据结构与算法】回溯法解题20240301

这里写目录标题 一、78. 子集1、nums [1,2,3]为例把求子集抽象为树型结构2、回溯三部曲 二、90. 子集 II1、本题搜索的过程抽象成树形结构如下&#xff1a; 三、39. 组合总和1、回溯三部曲2、剪枝优化 四、LCR 082. 组合总和 II1、思路2、树形结构如图所示&#xff1a;3、回溯…

命令行启动mongodb服务器的问题及解决方案 -- Unrecognized option: storage.journal

目录 mongodb命令行启动问题 -- Unrecognized option: storage.journal问题日志&#xff1a;问题截图&#xff1a;问题来源&#xff1a;错误原因&#xff1a;解决方式&#xff1a; mongodb命令行启动问题 – Unrecognized option: storage.journal 同样是格式出问题的问题分析和…

视频在线压缩

video2edit 一款免费的在线视频编辑软件&#xff0c;可以进行视频合并、视频剪辑、视频压缩以及转换视频格式等。 链接地址&#xff1a;在线视频编辑器和转换器 - 编辑&#xff0c;转换和压缩视频文件 打开视频压缩页面&#xff0c;上传想要压缩视频&#xff0c;支持MP4&…

SpringCloud搭建微服务之Consul服务注册与发现

1. Consul介绍 Consul是由HashiCorp公司使用Go语言开发的一款开源工具&#xff0c;主要用于实现分布式系统的服务发现和服务配置&#xff0c;其内置了服务注册与发现框架、分布式一致性协议实现、健康检查、Key-Value存储、多数据中心方案。Consul具有高可移植性&#xff0c;支…

LTE 网络与互联网的连接

LTE 网络与互联网的连接 当用户设备 UE&#xff08;如手机&#xff09;开机后&#xff0c;就登记到 LTE 网络&#xff0c;以便使用网络资源传送 IP 数据业务。 LTE 网络内的数据路径由两大部分组成&#xff1a; -空口无线链路&#xff08;UE→eNB&#xff09;。 -核心网中的隧…

【菜鸟入门!】Matlab零基础快速入门教程

数学建模竞赛中&#xff0c;编程软件是必不可缺少的&#xff0c;比如大家都熟知的MATLAB多数同学们都会经常用到&#xff0c;今天给大家介绍一些MATLAB的基本元素&#xff0c;希望帮助大家更好的掌握编写基本的函数&#xff01; 变量和数组 MATLAB 程序的基本数据单元是数组。一…

Opencv实战(5)平滑处理与常见函数

平滑处理 Opencv实战&#xff1a; Opencv(1)读取与图像操作 Opencv(2)绘图与图像操作 Opencv(3)详解霍夫变换 Opencv(4)详解轮廓 文章目录 平滑处理1.均值滤波2.方框滤波3.高斯滤波4.中值滤波5.双边滤波 常见函数(1).createTrackbar()(2).SetMouseCallback() 图像的平滑处理是…

Intel 芯片 Mac 如何重新安装系统

使用可引导安装器重新安装&#xff08;可用于安装非最新的 Mac OS&#xff0c;系统降级&#xff0c;需要清除所有数据&#xff0c;过程确保连接上网络&#xff0c;虽然这种方式不会下载 Mac OS&#xff0c;但是需要下载固件等信息&#xff09; 插入制作好的可引导安装器&#x…

使用docker方式测试部署django项目(客户催)

需求 1&#xff1a;已有django项目–weidanyewu 2&#xff1a;希望在服务器上测试部署–客户催 3&#xff1a;没完善django的启动 4&#xff1a;使用临时数据库进行演示 5&#xff1a;使用python3.10版本镜像 6&#xff1a;展示端口80 7&#xff1a;后台执行django程序 8&#…

信号系统之滤波器比较

比较 1&#xff1a;模拟与数字滤波器 大多数数字信号源自模拟电子设备。**如果需要对信号进行滤波&#xff0c;是在数字化之前使用模拟滤波器&#xff0c;还是在数字化后使用数字滤波器更好&#xff1f;**将通过两个对比来回答问题。 目标是提供 1 kHz的低通滤波器。模拟端是…

2023全球软件开发大会-上海站:探索技术前沿,共筑未来软件生态(附大会核心PPT下载)

随着信息技术的迅猛发展&#xff0c;全球软件开发大会&#xff08;QCon&#xff09;已成为软件行业最具影响力的年度盛会之一。2023年&#xff0c;QCon再次来到上海&#xff0c;汇聚了众多业界精英、技术领袖和开发者&#xff0c;共同探讨软件开发的最新趋势和实践。 一、大会…

网络安全攻防演练:企业蓝队建设指南

第一章 概述 背景 网络实战攻防演习是当前国家、重要机关、企业组织用来检验网络安全防御能力的重要手段之一,是对当下关键信息系统基础设施网络安全保护工作的重要组成部分。网络攻防实战演习通常是以实际运行的信息系统为攻击目标,通过在一定规则限定下的实战攻防对抗,最…

Django学习笔记-查询及修改MySQL数据库表的所有信息

1.在index中添加一个按钮,用于查询数据 2.urls配置find 3.views定义find,获取PopulationModel模型所有数据渲染到show.html页面上 4.创建show.html,遍历modellist的数据渲染到表格中显示 5.点击查询后页面显示如下 6.添加修改按钮,点击按钮,执行update,urls配置update …

R语言数学建模(二)—— tidymodels

R语言数学建模&#xff08;二&#xff09;—— tidymodels 文章目录 R语言数学建模&#xff08;二&#xff09;—— tidymodels前言一、示例数据集二、拆分数据集2.1 拆分数据集的常用方法2.2 验证集2.3 多层次数据2.4 其他需考虑问题 三、parsnip用于拟合模型3.1 创建模型3.2 …