C语言笔记(自定义类型:结构体、枚举、联合体 )

news2024/11/25 5:44:01

前言

        本文对自定义类型的结构体创建、使用、结构体的存储方式和对齐方式,枚举的定义、使用方式以及联合体的定义、使用和存储方式展开叙述,如有错误,请各位指正。

目录

前言

1 结构体

1.1 结构体的声明

1.2 结构体的自引用

1.3 结构体变量的定义和初始化

1.4 结构体变量的内存对齐

1.5 修改默认对齐数

1.6 结构体传参

2.位段

2.1 位段的内存分配

2.2 位段的跨平台问题

3.枚举

3.1枚举类型的定义

3.2枚举的优点

3.3枚举的使用

4. 联合(共用体)

4.1 联合类型的定义

4.2 联合的特点

4.3 联合大小的计算

1 结构体

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

1.1 结构体的声明
struct tag
{
member-list;
}variable-list;

tag                结构体标签

member-list  成员列表

variable-list   变量列表

注意:创建结构提变量的时候最后的不能丢掉

结构体就创建一个自定义的包含多种数据类型的数据类型

示例

创建一个描述学生的结构体数据类型 Stu 

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

特殊声明 :匿名结构体类型,没有结构体的标签,没有给结构体起名字。

示例1(创建没有标签的结构体)

struct
{
	int a;
	char b;
	float c;
}x;//x创建的结构体变量

        这种结构的使用只能现创现用,在不同的位置是无法创建同一类型的结构体变量的,创建变量需要结构体标签,没有标签就是创建不了变量了。

示例2(创建结构体的指针)

struct
{
int a;
char b;
float c;
} *p;

示例1和示例2中下方等式成立吗?

p = &x;

1.2 结构体的自引用

        结构体的自引用就是结构体中包含结构体的指针。

示例:在数据结构中数据的存放有链表性结构,链表中的每一处的节点都会存放一个数据,还可以根据节点找到下一个节点的地址,然后创建结构体;那么我结构体存放节点的数据和指向下一个节点的指针就可以了,这就是结构体的自引用了。

struct Node
{
    int data;//            节点的数据
    struct Node* next;//   下一个节点的地址
};

        结构的创建变量的时候名字较为复杂还有 unsigned int 、unsigned char等等 都可以使用 typedef重新定义名字,这样在创建变量的时候就简单了,如下

//重新定义变量
typedef unsigned int uint;
typedef unsigned char uchar;
typedef char u8;
typedef struct Stu Stu;
//创建变量
unit a;
unchar b;
u8 c;
Stu x;

需要注意

在结构体创新命名的时候,需要结构体有标签。

1.3 结构体变量的定义和初始化

        结构体定义就是创建结构体变量,以下是创建结构提变量的方式:


//方式1 创建结构体的时候创建全局变量
struct Point
{
	int x;
	int y;
}a1;
//方式2
struct Point a2;
//方式3
int main()
{
	struct Point a3;

	return 0;
}

        初始化和和数组的初始化较为相似,是应用{ }来初始换结构体创建的变量,在后面附上值就可以了,完全初始化,

struct Point
{
	int x;
	int y;
}a1 = {10,20};
struct Point a2 = {5,9};

int main()
{
	struct Point a3 = { 2,3 };

	return 0;
}

        不完全初始化(一个一个的给变量赋值)

struct S s1= { .num=10,.ch='q',.p.x=6, .p.y=10 };

嵌套结构体的初始化,有几个结构体就用几个{ }来创建变量,示例如下:

struct Point1
{
	int x;
	int y;
};
struct Point2
{
	int z;
	char ch;
	struct Point1 a1;
	float d;
};
int main()
{
	struct Point2 s = { 1,'a',{1,2},6.14f };
	return 0;
}

结构体的访问方式,分为两种,一种是使用 . 符号来访问,一种是使用 -> 符号来访问

struct Point
{
	int x;
	int y;
};
struct S
{
	int num;
	char ch;
	struct Point p;
	float d;
};

int main()
{
	//	初始化
	struct S s = { 3,'w',{1,2},3.15f };
	//访问
	printf("%d %c %d %d %0.1f\n", s.num,s.ch,s.p.x, s.p.y, s.d);

	return 0;
}
struct Stu
{
	char name[20];
	int age;
	char sex[20];
	float score;
};
int main()
{
	//打印结构体信息
	struct Stu s = { "张三", 20, "男", 95.0f };
	struct Stu *ps = &s;
	printf(" %s %d %s %.1f\n", ps->name, ps->age, ps->sex, ps->score);
	return 0;
}
1.4 结构体变量的内存对齐

        结构体的内存对齐决定了结构体的在内存中所占用的空间大小。

引入

        创建两个结构体,结构体中的变量类型相同,但是顺序不同,其内存大小一样吗?

struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct S1));//12
	printf("%d\n", sizeof(struct S2));//8
	return 0;
}

1.结构体的顺序不一样,内存不一样;

2.内存的大小和成员的数据类型有关吗?

结构体的对齐方式按照以下几条

1.结构体的第一成员,对齐到结构体在内存中的存放位置的0偏移处;

2.从第二个成员开始,每个成员都要对齐到(一个对齐数)的整数倍处;

对齐数:结构体成员自身大小和默认对齐数的较小值;

VS:默认对齐数为8;

Linux gcc :没有默认对齐数,对齐数就是结构题成员的自身大小;

3.结构体的总大小,必须是所有成员的对齐数中最大对齐数的整数倍。

4.如果结构体中嵌套了结构体成员,要将嵌套的结构体成员的对齐到自己的成员中最大的对齐数的整数。(结构体的总大小必须是最大对齐数的整数倍,包含请嵌套结构体成员的对齐数,是所有对齐数的最大值)

S1的结构体存储的方式

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

 (1)c1是第一个成员,从0偏移量存储,占用一个字节(灰色);

(2)i为整型变量,对齐数为4,默认对齐数为8,取较小值为4,偏移量为4,偏移量 1,2,3处内存浪费掉了(黄色);

(3)c2字符变量,对齐数为1,默认对齐数为8,取较小值为1,占用偏移量为8的位置(红色);

(4)确定结构体的大小,从c1到c2处,占用了9个字节的空间,取结构体成员的最大对齐数4,因此内存要占用12个字节,浪费6个字节(蓝色)。

S1的结构体存储的方式

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

(1)c1是第一个成员,从0偏移量存储,占用一个字节(灰色);

(2)c2字符变量,对齐数为1,默认对齐数为8,取较小值为1,偏移量是对齐数的倍数 2,占用偏移量为2的位置(红色);

(3)i为整型变量,对齐数为4,默认对齐数为8,取较小值为4,偏移量为4,去偏移量的倍数 4,偏移量 2,3处内存浪费掉了(黄色);

(4)确定结构体的大小,取结构体成员的最大对齐数4,因此内存要占用8个字节,浪费2个字节空间(蓝色)。

使用 offsetof函数来验证上述的偏移量是否正确,这个函数就是计算偏移量的,头文件是stddef,

验证程序

struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};
int main()
{
	printf("%d\n", sizeof(struct S1));//12
	printf("%d\n", offsetof(struct S1, c1));//0
	printf("%d\n", offsetof(struct S1,i));//4
	printf("%d\n", offsetof(struct S1,c2));//8
	return 0;
}

嵌套结构体内存对齐,

#include <stdio.h>
#include <stddef.h>
struct S2
{
	char c1;
	char c2;
	int i;
};
struct S3 
{
	double d;
	struct S2 s2;
	int a;
};
int main()
{
	printf("%d\n", sizeof(struct S3));//24
	printf("%d\n", offsetof(struct S3,d));//0
	printf("%d\n", offsetof(struct S3,s2));//8
	printf("%d\n", offsetof(struct S3,a));//16
	return 0;
}

S3是如何对齐呢?

struct S3 
{
	double d;
	struct S2 s2;
	int a;
};

(1)d是第一个成员,从0偏移量存储,占用8个字节(灰色);

(2)s3为结构体变量,结构体成员最大的对齐数为4,默认对齐数为8,取较小值为4,偏移量是对齐数的倍数 8,占用偏移量为8的位置(黄色);

(3)a为整型变量,对齐数为4,默认对齐数为8,取较小值为4,偏移量取16,取偏移量的倍数 16(黄色);

(4)确定结构体的大小,取结构体成员的最大对齐数8,因此内存要占用24个字节,浪费4个字节空间(蓝色)。

为什么要对齐呢?

1. 程序移植: 不是所有的平台数据的存储方式和访问方式是一样的。
2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

总结:结构体的对齐就是利用内存换取运行时间的手段。

如何节省空间?

        将占用空间小的成员集中到一起。

1.5 修改默认对齐数
#pragma pack()//恢复默认对齐数
#pragma pack(1)//设置对齐数为1
#include <stdio.h>
#include <stddef.h>
#pragma pack(1)//设置对齐数为1
struct S1
{
	char c1;
	int i;
	char c2;
};
#pragma pack()//恢复默认对齐数

int main()
{
	printf("%d\n", sizeof(struct S1));//6
	printf("%d\n", offsetof(struct S1,c1));//0
	printf("%d\n", offsetof(struct S1,i));//1
	printf("%d\n", offsetof(struct S1,c2));//5
	return 0;
}

此时S1的空间对齐方式

(1)c1是第一个成员,从0偏移量存储,占用一个字节(灰色);

(2)i为整型变量,对齐数为1,偏移量为1,(黄色);

(3)c2字符变量,对齐数为1,占用偏移量为5的位置(红色);

(4)确定结构体的大小,从c1到c2处,占用了6个字节的空间。

1.6 结构体传参

        结构体传参一般采用地址传参的方式,在传递值传参的时候,需要重新创建变量,浪费大量的内存空间,传址调用较为省空间。

struct S
{
    int data[1000];
    int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
    printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
    printf("%d\n", ps->num);
}
int main()
{
    print1(s);  //传结构体
    print2(&s); //传地址
    return 0;
}

2.位段

位段的声明和结构体类似,有两种不同的标志

1.位段的成员必须是 int 、unsigned int、或者是signed int;

2.位段的成员名后有一个冒号和一个数字。

struct A
{
    int _a:2;
    int _b:5;
    int _c:10;
    int _d:30;
};

A是一个位段类型,位段的大小是多少呢?

printf("%d", sizeof(struct A));//8

原本4个整型数据,占据16个字节,如何在内存中限制到8个字节的呢?

2.1 位段的内存分配

1. 位段的成员可以是 int unsigned、 int、 signed int 、 char 类型
2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

struct S
{
    char a:3;
    char b:4;
    char c:5;
    char d:4;
};
    struct S s = {0};
    s.a = 10;
    s.b = 12;
    s.c = 3;
    s.d = 4;

        位段开辟空间一次开辟一个字节,不够使用的话再开辟另一个字节;位段是从低地址到高地址存储的,在每个字节中也是从低位向高位存储;

2.2 位段的跨平台问题

1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机
器会出问题。
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是
舍弃剩余的位还是利用,这是不确定的。

特点:位段和结构体相比,位段的存储空间为共用空间,位段更加节省空间,但是存在跨平台问题。

3.枚举

3.1枚举类型的定义

可以被一一列举的变量,语法形式和结构体类似,例如生活中的,

1.一周的星期一到星期日有限的7天,可以一一列举;

2.性别有:男、女分别;

3.一年有12个月,可以一一列举。

enum Day
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};
enum Sex
{

    MALE,
    FEMALE,
    SECRET
};

三原色

enum Color
{
    RED,
    GREEN,
    BLUE

};

上述是有可能取到的值,默认从零开始一次递增,在定义的时候可以赋初值,示例

#include <stdio.h>
enum Day
{
	Mon = 1,
	Tues = 2,
	Wed = 3,
	Thur = 4 ,
	Fri = 5,
	Sat = 6,
	Sun = 7 
};
int main()
{
	printf("%d\n", Mon);//1
	printf("%d\n", Tues);//2
	return 0;
}

        枚举常量就是给特定的字符赋予一定的数值,在后续的使用中Mon和1等价。

3.2枚举的优点

和#define相比枚举创建的常量可以在调试中显示,而宏定义是不可以的。

1. 增加代码的可读性和可维护性;
2. 和#define定义的标识符比较枚举有类型检查,更加严谨;
3. 防止了命名污染(封装);
4. 便于调试;
5. 使用方便,一次可以定义多个常量。

3.3枚举的使用

下述代码是用于C51单片机的按键控制LED亮灭的程序,创建的枚举变量使用的时候程序较好理解,如果将KEY1_PRESS为1的话,并不是特别的直观的表达出按键1以将按下。

#include <REGX52.H>
#include <stdio.h>
//引脚定义
#define  SMG_A_DP_PORT  P1 
sbit KEY1 = P0 ^ 0;
sbit KEY2 = P0 ^ 1;
sbit KEY3 = P0 ^ 2;
sbit KEY4 = P0 ^ 3;
sbit LED1 = P2 ^ 0;
sbit LED2 = P2 ^ 1;
sbit LED3 = P2 ^ 2;
sbit LED4 = P2 ^ 3;

enum KEY
{
	KEY_UNPRESS = 0,
	KEY1_PRESS = 1,
	KEY2_PRESS = 2,
	KEY3_PRESS = 3,
	KEY4_PRESS = 4,
};//枚举
char key_scan(mode);//当mode=0的时候 单次扫描 mode=1 连扫
void main()
{

	unsigned char  ret = 0;

	while (1)
	{
		ret = key_scan(0);
		switch (ret)
		{
		case KEY1_PRESS:
		{
			LED1 = !LED1;
			break;
		}
		case KEY2_PRESS:
		{
			LED2 = !LED2;
			break;
		}
		case KEY3_PRESS:
		{
			LED3 = !LED3;
			break;
		}
		case KEY4_PRESS:
		{
			LED4 = !LED4;
			break;
		}

		}
	}

}

//延时函数 当1=ten_us,延时10us
void delay_10us(unsigned int ten_us)
{
	while (ten_us--);
}
char key_scan(mode)//当mode=0的时候 单次扫描 mode=1 连扫
{
	static char key = 1;
	if (mode)
	{
		key = 1;
	}
	if (key == 1 && (KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0))
	{
		key = 0;
		delay_10us(1000);
		if (KEY1 == 0)
			return KEY1_PRESS;
		else if (KEY2 == 0)
			return KEY2_PRESS;
		else if (KEY3 == 0)
			return KEY3_PRESS;
		else if (KEY4 == 0)
			return KEY4_PRESS;
	}
	else if (KEY1 == 1 && KEY2 == 1 && KEY3 == 1 && KEY4 == 1)
	{
		key = 1;
	}
	return KEY_UNPRESS;
}

4. 联合(共用体)

4.1 联合类型的定义

联合是一种特殊的自定义类型,定义的变量也包含一系列的成员这些成员会共用一块内存空间。

union UN 
{
	char c;
	int i;
};
int main()
{
	union UN un;
	printf("%d\n", sizeof(un));//4
	printf("%p\n", &un);//00EFFB08
	printf("%p\n", &(un.c));//00EFFB08
	printf("%p\n", &(un.c));//00EFFB08
	return 0;
}

        三次取地址的结果是一样的,说明c和i的起始地址的是一样,可以得出,两个变量占用得空间开始是一样得,当然两个变量是不可以同时使用得,c占用4个字节的第一个字节,i占用四个字节,如图

4.2 联合的特点

        联合的成员是共用同一块内存空间的,联合变量的大小至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

int main()
{
	union Un
	{
		int i;
		char c;
	};
	union Un un;
	//下面输出的结果是什么?
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);//11223355

	return 0;
}

        un的前四个字节为11223344,后有将44修改为了55,因为VS2017上位小端存储。

可以封装成函数判断大小端存储:

#include<stdio.h>
int check_sys()
{
	union Un
	{
		int i;
		char c;
	}un;
	un.i = 1;
	return un.c;//判断变量,低位是否为1或者0
}
int main()
{
	int ret = check_sys();
	if (ret)
	{
		printf("小端存储");
	}
	else
		printf("大端存储");
	return 0;
}
4.3 联合大小的计算

1.联合的大小至少是最大成员的大小。
2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

int main()
{
	union Un1
	{
		char c[5];
		int i;
	};
	union Un2
	{
		short c[7];
		int i;
	};
	//下面输出的结果是什么?
	printf("%d\n", sizeof(union Un1));//8
	printf("%d\n", sizeof(union Un2));//16
}

Un1的内存大小为8

(1).c[5]的对齐数位1,占用5个字节的空间

(2).i的对齐数为4,占用内存4个字节的空间,

(3)最大对齐数为4,再取4的倍数,内存大小为8个字节;

Un2的内存大小为16

(1).c[7]的对齐数位2,占用14个字节的空间

(2).i的对齐数为4,占用内存4个字节的空间,

(3)最大对齐数为4,再取4的倍数,内存大小为16个字节;

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

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

相关文章

string的实际应用 -- 大数相加 、大数相乘

前言&#xff1a;哎&#xff0c;做题好难o(╥﹏╥)o&#xff0c;有时候想不到&#xff0c;而有时候则是想到了却没办法理清思路&#xff0c;转化为代码。有必要反思了┓(;_&#xff40;)┏&#xff0c;是否是做的太少了&#xff0c;或是自己的基础欠缺。 大学总是有些迷茫~ ​​…

STM32-- keil 的option for target使用

keil版本号 1.device界面 如&#xff1a;stm32f103c8t6的工程&#xff0c;可以直接在device这里修改成stm32f103vct6&#xff0c;虽然引脚不一样&#xff0c;但是很多一样的地方&#xff0c;可以直接使用&#xff0c;有些不修改也可以下载程序。 2.target xtal的设置不起作用了…

shell脚本9完结,保姆篇---春不晚

免责声明 学习视频来自 B 站up主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 泷羽sec官网&#xff1a;http…

【数据分享】2024年我国省市县三级的住宿服务设施数量(8类住宿设施/Excel/Shp格式)

宾馆酒店、旅馆招待所等住宿服务设施的配置情况是一个城市公共基础设施完善程度的重要体现&#xff0c;一个城市住宿服务设施种类越丰富&#xff0c;数量越多&#xff0c;通常能表示这个城市的公共服务水平越高&#xff01; 本次我们为大家带来的是我国各省份、各地级市、各区…

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性&#xff1f;3.什么样的消息会成为死信&#xff1f;4.死信交换机的使用场景是什么&#xff1f;5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

在kali用msfpc远程控制Windows

本次实验我们将使用msfpc生成windows下的被控端&#xff0c;并使用metasploit渗透工具进行远程控制。 一、实验环境 Windows主机IP&#xff1a; 192.168.167.1 虚拟机Kali IP&#xff1a; 192.168.167.100 二、实验过程 1、安装msfpc apt-get install msfpc 2、生成windows…

SDIO WIFI模组Clock EMC问题

问题&#xff1a; 某产品采用SDIO3.0的WIFI模组&#xff0c;测试3米场地辐射出现333MHz和500MHz频点超标。 分析&#xff1a; 1、一开始分析板子上没有对应333MHz,499.5MHz的频点倍频&#xff0c;因此直接拔掉产品上所有的外部接线&#xff0c;测试还是超标。表明辐射源头出…

MCU(一) 时钟详解 —— 以 GD32E103 时钟树结构为例

微控制器 (MCU) 的时钟系统是系统运行的核心&#xff0c;它提供了各模块所需的时钟信号。本文以 GD32E103 系列 MCU 为例&#xff0c;详细讲解其 时钟树结构&#xff08;Clock Tree&#xff09;。通过理解时钟源、分配与预分频器设置&#xff0c;可以灵活配置系统时钟以实现高性…

【方案库】从单张照片快速重建3D场景:Flash3D详解

一、Flash3D是什么? Flash3D 是一项革命性的AI技术,能够从单张普通照片快速重建3D场景。简单来说,你只需要提供一张照片,Flash3D 就能帮你还原出这个场景的立体效果。这项技术在房地产、建筑设计、虚拟现实等多个领域都有着广泛的应用前景。 二、主要特点 一张就够:只需…

QT QFormLayout控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例&#xff0c;包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizonta…

如何在 Ubuntu 22.04 上安装 Metabase 数据可视化分析工具

简介 Metabase 提供了一个简单易用的界面&#xff0c;让你能够轻松地对数据进行探索和分析。通过本文的指导&#xff0c;你将能够在 Ubuntu 22.04 系统上安装并配置 Metabase&#xff0c;并通过 Nginx 进行反向代理以提高安全性。本教程假设你已经拥有了一个非 root 用户&…

c#:winform调用bartender实现打印(学习整理笔记)

效果 学习路径 C# winform调用Bartender进行自定义打印、批量打印、检索文件夹中的模板_哔哩哔哩_bilibili 一、初始环境搭建见&#xff1a; c#:winform引入bartender-CSDN博客https://blog.csdn.net/weixin_46001736/article/details/143989473?sharetypeblogdetail&s…

1123--日期类

目录 一 java 1. Date类 2. calendar类 3. 第三代日期类‘ 3.1 常用方法 3.2 格式化操作 一 java 1. Date类 2. calendar类 3. 第三代日期类‘ 3.1 常用方法 3.2 格式化操作

当产业经济插上“数字羽翼”,魔珐有言AIGC“3D视频创作大赛”成功举办

随着AI技术的飞速发展&#xff0c;3D数字人技术已成为驱动各行各业转型升级的重要力量。在这一背景下&#xff0c;2024山东3D数字人视频创作大赛应运而生&#xff0c;并在一番激烈的角逐后圆满落幕&#xff0c;为科技与创意的交融写下浓墨重彩的一笔。 11月20日&#xff0c;一…

InstantStyle容器构建指南

一、介绍 InstantStyle 是一个由小红书的 InstantX 团队开发并推出的图像风格迁移框架&#xff0c;它专注于解决图像生成中的风格化问题&#xff0c;旨在生成与参考图像风格一致的图像。以下是关于 InstantStyle 的详细介绍&#xff1a; 1.技术特点 风格与内容的有效分离 &a…

使用EFK收集k8s日志

首先我们使用EFK收集Kubernetes集群中的日志&#xff0c;本次实验讲解的是在Kubernetes集群中启动一个Elasticsearch集群&#xff0c;如果企业内已经有了Elasticsearch集群&#xff0c;可以直接将日志输出至已有的Elasticsearch集群。 文章目录 部署elasticsearch创建Kibana创建…

Rust 力扣 - 2266. 统计打字方案数

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 这题可以先求按了多少次相同连续的按钮&#xff0c;所有的连续相同按钮表示的方案数的乘积就是本题答案 我们的关键问题就转换成了按n个连续相同按钮表示的方案数 设f(i)表示按i个连续相同按钮表示的方案数 如…

[Redis#0] iredis: linux上redis超好用的环境配置

目录 Features 特征 Install 安装 Pip Brew Linux的 Download Binary 下载 Binary Usage 用法 Using DSN 使用 DSN Change The Default Prompt更改默认提示 Configuration 配置 Keys Development 发展 Release Strategy 发布策略 Setup Environment 设置环境 De…

flutter 专题十七 Flutter Flar动画实战

Flutter Flar动画实战 在Flare动面出现之前&#xff0c;Flare动画大体可以分为使用AnimationController控制的基础动画以及使用Hero的转场动画&#xff0c;如果遇到一些复杂的场景&#xff0c;使用这些动画方案实现起来还是有难度的。不过&#xff0c;随着Flutter开始支持Flar…

Wekan看板安装部署与使用介绍

Wekan看板安装部署与使用介绍 1. Wekan简介 ​ Wekan 是一个开源的看板式项目管理工具&#xff0c;它的配置相对简单&#xff0c;因为大多数功能都是开箱即用的。它允许用户以卡片的形式组织和跟踪任务&#xff0c;非常适合敏捷开发和日常任务管理。Wekan 的核心功能包括看板…