C语言——自定义类型

目录

结构体

概念

结构体变量的创建和初始化

结构体的自引用

结构体的内存对齐

内存对齐存在的原因

合理设计结构体

方法一

方法二

结构体传参

结构体实现位段

什么是位段

位段的内存分配

位段的跨平台问题

注意

联合体

概念

验证

优点

小应用

什么是大小端?

用联合体判断大小端

枚举

概念

优点

使用注意


我们以前见到的 char,bool,short,int,long long,float,double,long double都是内置类型。

自定义类型,从名字上来看,也就是我们自己创造定义的类型

包括数组类型,结构体类型(struct),枚举类型(enum),联合体类型(union)

结构体

概念

结构是⼀些 值的集合 ,这些值称为 成员变量
结构的每个成员 可以是不同类型的变量
结构体声明(注意:结构体最后有一个分号)
struct tag
{member-list;
//成员变量列表
}variable-list;
//结构体变量列表

例:描述一个学生

//定义一个结构体
struct Student
{//结构体成员变量列表char name[20];//姓名int age;//年龄char sex[10];//性别char number[20];//学号
}st1,st2;//结构体变量列表

结构体变量的创建和初始化

方法一:直接在结构体后面创建结构体变量和初始化

//定义一个结构体
struct Student
{//结构体成员变量列表char name[20];//姓名int age;//年龄char sex[10];//性别char number[10];//学号
}st1 = { "张三",18,"男","1234567" },st2 = { "李丽",24,"女","1234568" };//结构体变量列表#include<stdio.h>
int main()
{printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st1.name, st1.age, st1.sex, st1.number);printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st2.name, st2.age, st2.sex, st2.number);return 0;
}

方法二:在需要的函数中进行结构体变量的创建和初始化

//定义一个结构体
struct Student
{//结构体成员变量列表char name[20];//姓名int age;//年龄char sex[10];//性别char number[10];//学号
};//分号#include<stdio.h>
int main()
{struct Student st1 = { "张三",18,"男","1234567" };struct Student st2 = { "李丽",24,"女","1234568" };printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st1.name, st1.age, st1.sex, st1.number);printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st2.name, st2.age, st2.sex, st2.number);return 0;
}

当然,在初始化的时候我们也可以按照自己的顺序给结构体变量进行初始化

//定义一个结构体
struct Student
{//结构体成员变量列表char name[20];//姓名int age;//年龄char sex[10];//性别char number[10];//学号
}st1,st2;//分号#include<stdio.h>
int main()
{struct Student st1 = { .name="张三",.sex="男",.number="1234567",.age=18 };//也可以按照自己的顺序进行初始化struct Student st2 = { "李丽",24,"女","1234568" };printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st1.name, st1.age, st1.sex, st1.number);printf("name:%s\nage:%d\nsex:%s\nnumber:%s\n", st2.name, st2.age, st2.sex, st2.number);return 0;
}

结构体的自引用

我们说结构体里面可以是不同类型的变量,那么结构体里面可不可以包含一个类型为该结构本身的成员呢?

答案是不可以的,比如我们定义一个链表的结点。

struct Node
{int data;struct Node next;
};

这样子进行定义的话,⼀个结构体中再包含⼀个同类型的结构体变量,那么结构体变量的⼤⼩就会⽆穷的⼤,是不合理的。

正确方式:

struct Node
{int data;struct Node* next;
//next保存下一个结点的地址
};

我们也可以进行一定的优化(使用重命名的方式)

typedef struct Node
{int data;struct Node* next;
//虽然后面结构体重命名为Node,但是到这里编译器还没有识别,依然写成
//struct Node的形式
}Node;

结构体的内存对齐

计算结构体大小,就需要知道结构体内存对齐的规则

1. 结构体的 第⼀个成员对⻬到和结构体变量起始位置偏移量为0 的地址处
2. 其他成员变量要对齐到 对齐数整数倍 的地址处
对⻬数 = 编译器默认对⻬数 与该 成员变量⼤⼩ 较⼩值
VS 中默认的值为 8
- Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3. 结构体总⼤⼩为 最⼤对⻬数 (结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍
4. 如果嵌套了结构体的情况, 嵌套的结构体成员 对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是 所有最⼤对⻬数 (含嵌套结构体中成员的对⻬数)的 整数倍
看了这规则,不如来几个题练练手
#include<stdio.h>
int main()
{//练习1struct S1{char c1;int i;char c2;};printf("%zd\n", sizeof(struct S1));//练习2struct S2{char c1;char c2;int i;};printf("%zd\n", sizeof(struct S2));//练习3struct S3{double d;char c;int i;};printf("%zd\n", sizeof(struct S3));//练习4-结构体嵌套问题struct S4{char c1;struct S3 s3;double d;};printf("%zd\n", sizeof(struct S4));return 0;
}

请在评论区留下你的答案,我们马上揭晓谜底~

我们通过下面的来进行理解答案

#include<stdio.h>
int main()
{//练习1struct S1{//vs默认对齐数为8char c1;//1   8   1int i;  //4   8   要对齐到该成员变量int类型字节大小4的整数倍——4+4char c2;//1   8   8+1——9//结构体总大小为成员变量最大对齐数4的整数倍//12};printf("%zd\n", sizeof(struct S1));//练习2struct S2{char c1;//1  8   1char c2;//1  8   1+1——2int i;  //4  8   2+4//结构体总大小为成员变量最大对齐数4的整数倍//8};printf("%zd\n", sizeof(struct S2));//练习3struct S3{double d;//8   8   8char c;  //1   8   8+1——9int i;   //4   8   12+4——16//结构体总大小为成员变量最大对齐数8的整数倍//16满足};printf("%zd\n", sizeof(struct S3));//练习4-结构体嵌套问题struct S4{char c1;      //1   8    1struct S3 s3; //16   8    8+16——24//结构体S3大小为16,最大对齐数为8double d;     //8   8    24+8——32//结构体总大小为成员变量最大对齐数8的整数倍//32满足};printf("%zd\n", sizeof(struct S4));return 0;
}

内存对齐存在的原因

那么为什么会有结构体对齐呢?

平台原因 (移植原因)
       不是所有的硬件平台都能访问任意地址上的任意数据 的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
性能原因
数据结构(尤其是栈)应该尽可能地 在⾃然边界上对⻬ ,原因在于, 为了访问未对⻬的内存,处理器需要作两次内存访问 ;⽽ 对⻬的内存访问仅需要⼀次访问 。假设⼀个处理器总是从内存中取8个字节,则地 址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数,那么就可以用 ⼀个内存操作来读或者写值。否则,我们可能需要执⾏两次内存访问,因为对象可能被分放在两 个8字节内存块中。
总结:结构体的内存对⻬是拿 空间来换取时间 的做法,提高程序的运行效率

合理设计结构体

如果在设计结构体的时候,我们既要 满⾜对⻬ ,⼜要 节省空间 ,我们可以怎么做呢?

方法一

让占⽤空间⼩的成员尽量集中在⼀起
比如下面这两个结构体:
#include<stdio.h>
int main()
{struct s1{char c1;char c2;int n;};printf("sizeof(struct s1)==%zd\n", sizeof(struct s1));struct s2{char c1;int n;char c2;};printf("sizeof(struct s2)==%zd\n", sizeof(struct s2));return 0;
}

我们可以看见虽然这两个结构体的包含的成员变量相同,但是它们的结构体大小是不一样的,这是因为在对齐结构体的时候它们的对齐位置是不一样的。

所以定义一个结构体的时候让占⽤空间⼩的成员尽量集中在⼀起,就可以节省空间。

方法二

修改默认对⻬数
我们知道VS的默认对齐数是8,事实上,结构体在对⻬⽅式不合适的时候,我们可以修改这个默认对齐数。
使用 #pragma 这个预处理指令,改变编译器的默认对⻬数
#include<stdio.h>
#pragma pack(1)//修改默认对齐数为1
struct s1
{char c1;char c2;int n;
};struct s2
{char c1;int n;char c2;
};
void test1()
{printf("test1:\n");printf("sizeof(struct s1)==%zd\n", sizeof(struct s1));printf("sizeof(struct s2)==%zd\n", sizeof(struct s2));}
int main()
{test1();return 0;
}

如果想让它恢复成原来编译器的默认对齐数只需要加上

#pragma pack()//恢复到编译器默认对齐数

#include<stdio.h>
#pragma pack(1)//修改默认对齐数为1
struct s1
{char c1;char c2;int n;
};
#pragma pack()//恢复到编译器默认对齐数
struct s2
{char c1;int n;char c2;
};
void test1()
{printf("test1:\n");printf("sizeof(struct s1)==%zd\n", sizeof(struct s1));printf("sizeof(struct s2)==%zd\n", sizeof(struct s2));}
int main()
{test1();return 0;
}

结构体传参

在前面学习函数的时候我们知道有传值传参和传址传参

#include<stdio.h>
struct S
{int data[10];int num;
};
struct S s = { {1,2,3,4}, 100 };
//结构体传参
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;
}

在上面的代码中,无论传参是传结构体还是传结构体的地址,都达到了我们想要的效果。

那么结构体传参哪一个更好呢?

答案是结构体地址传参

原因
1.函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
2.如果传递⼀个结构体对象的时候,结构体过⼤,参数压栈的的系统开销⽐较⼤,
会导致 性能的下降

结构体实现位段

什么是位段

位段的声明和结构是类似的,但是存在两个不同:
1. 位段的成员必须是 int unsigned int signed int (结构体可以有其他类型)
在C99中位段成员的类型也可以 选择其他类型。
2. 位段的成员名后边有⼀个冒号和⼀个数字(结构体成员名后面没有内容)
例如:
struct A
{int _a:2;int _b:5;int _c:10;int _d:20;
};
A就是⼀个位段类型,那么位段A所占内存的⼤⼩是多少呢?
位段内存大小为8,这是为什么呢?
我们首先需要知道位段的内存分配是什么样子的。

位段的内存分配

1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型
2. 位段的空间上是 按照需要 以4个字节( int )或者1个字节( char )的⽅式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。
我们来看看一个例子:
#include<stdio.h>
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{struct S s = { 0 };printf("test1:%zd\n", sizeof(s));s.a = 10;s.b = 12;s.c = 3;s.d = 4;}

我们在VS编译器上进行验证,我们猜想首先位段成员类型为char,按照需要以一个字节(8个比特位)空间来开辟,a要占用2个比特位,b占用4个比特位,c占用5个比特位,d占用4个比特位,a、b一起占用了6个比特位(剩余两个比特位,不够存储c,浪费掉这两个比特位,另外开辟一个字节),c占用五个字节,剩余三个比特位,不够存储d,浪费掉这三个比特位,另外开辟一个字节。所以位段A的字节大小为3,我们一起来验证一下。

所以说明在VS编译器上,剩余的比特位是浪费掉的,如果没有浪费那么应该是两个字节(16个比特位)。

后面的代码再对a,b,c,d所在的内存放入数据。

通过调试我们发现是正确的。
所以这个代码可以得出:
在VS编译器上:
1.char——一个字节一个字节进行内存空间开辟
2.一个字节内部从右向左使用
3.剩余的比特位不够下一个成员使用时,浪费掉,开辟新的内存进行存放
所以在最开始的代码中, 位段的空间上按4个字节(32个比特位)进行开辟,_a要占用2个比特位,_b占用5个比特位,_c占用10个比特位,_d占用20个比特位,_a和_b和_c一起占用了17个比特位,剩余15个比特位不够_d使用,另外开辟四个字节进行存储,所以字节大小为8.

位段的跨平台问题

1. int 位段被当成有符号数还是⽆符号数是不确定的。
2. 位段中最⼤位的数⽬不能确定
(16位机器最⼤16,32位机器最⼤32,如果写成27,在16位机器会 出问题)
3. 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
4. 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利⽤,这也是不确定的。
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在,我们应该根据实际情况进行使用。

注意

位段一般是 ⼏个成员共有同⼀个字节 ,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位 置处是没有地址的。
内存中 每个字节分配⼀个地址 ,⼀个字节内部的 bit位是没有地址的
所以不能对位段的成员使⽤&操作符,这样就 不能使⽤scanf直接给位段的成员输⼊值 ,只能是先输⼊ 放在⼀个变量中,然后赋值给位段的成员。
#include<stdio.h>
struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 20;
};
int main()
{struct A sa = { 0 };//scanf("%d", &sa._b);//这是错误的//正确的⽰范int b = 0;scanf("%d", &b);sa._b = b;return 0;
}

联合体

概念

像结构体⼀样,联合体也是 由⼀个或者多个成员构成 ,这些成员可以不同的类型。
编译器 只为最⼤的成员分配⾜够的内存空间
联合体的特点是 所有成员共⽤同⼀块内存空间 ,所 以联合体也叫:共⽤体。
如果 给联合体其中⼀个成员赋值,其他成员的值也会跟着变化。
#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };//计算联合体变量的大小printf("%d\n", sizeof(un));return 0;
}

大小为4个字节,这是为什么呢?

我们前面提到联合体的特点是所有成员共⽤同⼀块内存空间,编译器只会为最大的联合体成员分配足够的空间。

我们来看看下面的代码

#include <stdio.h>
union Un1
{char c[5];int i;
};
union Un2
{short c[7];int i;
};
int main()
{//输出的结果是什么?printf("%zd\n", sizeof(union Un1));printf("%zd\n", sizeof(union Un2));return 0;
}

上面进行了分析和解释,所以

⼀个联合变量的大小,⾄少是最⼤成员的大小(因为联合至少得有能⼒保存最⼤的那个成员)

当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍

验证

#include <stdio.h>
//联合类型的声明
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };// 输出的结果是⼀样的吗?printf("%p\n", &(un.i));printf("%p\n", &(un.c));printf("%p\n", &un);return 0;}

我们可以发现,这三个地址是一样的,这也就验证了联合体成员共用了一块内存空间。

我们来看看下面的代码:

#include<stdio.h>
union Un
{char c;int i;
};
int main()
{//联合变量的定义union Un un = { 0 };un.i = 0x11223344;un.c = 0x55;printf("%x\n", un.i);return 0;
}

我们发现将i的第4个字节的内容修改为55了,这也就是因为联合体成员共用一个内存空间。

优点

使用联合体有什么好处呢?

显而易见,使⽤联合体是可以 节省空间 的,因为联合体成员是共用一块内存空间的,联合体会至少开辟最大成员的空间大小,而结构体会给每一个成员开辟相应的空间。
比如我们需要保存 三种商品:图书、杯⼦、衬衫的信息,每⼀种商品都有:库存量、价格、商品类型和商品类型这些共同信息,每一个商品还有一些特殊信息【 图书:书名、作者、⻚数 】 【杯⼦:设计 】【 衬衫:设计、可选颜⾊、可选尺⼨】
我们可以写出下面的结构体
struct goods
{//公共属性int stock_number;//库存量double price; //定价int item_type;//商品类型//特殊属性char title[20];//书名char author[20];//作者int num_pages;//页数char design[30];//设计int colors;//颜⾊int sizes;//尺⼨
};

结构体里面包括了所有的属性,需要哪一个再去进行初始化以及使用,但是这样就会导致结构体偏大,造成空间的浪费。我们可以一起使用结构体和联合体来进行改造,比如:

struct goods
{int stock_number;//库存量double price; //定价int item_type;//商品类型union {struct{char title[20];//书名char author[20];//作者int num_pages;//页数}book;struct{char design[30];//设计}mug;struct{char design[30];//设计int colors;//颜⾊int sizes;//尺⼨}shirt;}item;
};

联合体就会为占内存空间最大的结构体分配足够的空间,这也就节省了内存空间。

小应用

写⼀个程序,判断当前机器是⼤端?还是⼩端?

什么是大小端?

超过⼀个字节的数据 在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分
⼤端字节序存储 ⼩端字节序存储。不同的编译器存储顺序不一样。
⼤端(存储)模式:
数据的 低位字节 内容保存在 内存的⾼地址 处,⽽数据的⾼位字节内容,保存在内存的低地址处。
⼩端(存储)模式:
数据的 低位字节 内容保存在 内存的低地址 处,⽽数据的⾼位字节内容,保存在内存的⾼地址处。

用联合体判断大小端

int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是⼩端,返回0是⼤端
}int main()
{if (check_sys)//1为真{printf("小端\n");}else{printf("大端\n");}return 0;
}

编译器取地址会从低地址开始取,这里返回了1,也就是低字节的内容存放在低地址处,说明VS为小端机器。

枚举

概念

枚举就是⼀⼀列举, 把可能的取值⼀⼀列举
比如,我们实际生活中一周有七天,一年有12个月,这些都是可以一一列举的,我们用枚举来表示,就是
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun//中间用逗号隔开
};//末尾有分号!!!enum Month
{Jan,Feb,Mar, ‌Apr,May,‌Jun, ‌Jul,‌Aug,‌Sept,‌Oct,Nov,Dec
};
以上定义的 enum Day enum Month 都是枚举类型。
{ }中的内容是枚举类型的可能取值,也就是枚举常量 。
这些可能取值都是有值的, 默认从0开始,依次递增1 ,当然在声明枚举类型的时候也可以赋初值。
例:
#include<stdio.h>
enum Color//颜⾊
{RED,GREEN = 3,BLUE
};int main()
{printf("%d\n", RED);printf("%d\n", GREEN);printf("%d\n", BLUE);return 0;
}
//第一个枚举常量默认为0,也可以初始化,没有初始化的枚举常量是上一个枚举常量的值加一

优点

我们可以使⽤ #define 定义常量,为什么要使⽤枚举?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
3. 便于调试,预处理阶段会删除 #define 定义的符号
4. 使⽤⽅便,⼀次可以定义多个常量
5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤

使用注意

在C语⾔中是可以 拿整数给枚举变量赋值 的,但是在C++是不⾏的,C++的类型检查⽐较严格。

enum Color//颜⾊
{RED = 1,GREEN = 2,BLUE = 4
};
enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Unity】对象池 - 未更新完

自定义泛型对象池 文章目录 自定义泛型对象池封装泛型类例子 使用Unity自带对象池 封装泛型类 public abstract class MyPool<T> : MonoBehaviour where T :Component {[SerializeField] protected T prefab; // 生成的预制体[SerializeField] protected int defaultNum…

鸿蒙环境服务端签名直传文件到OSS

本文介绍如何在鸿蒙环境下将文件上传到OSS。 背景信息 鸿蒙环境是当下比较流行的操作环境&#xff0c;与服务端签名直传的原理类似&#xff0c;鸿蒙环境上传文件到OSS是利用OSS提供的PutObject接口来实现文件上传到OSS。关于PutObject的详细介绍&#xff0c;请参见PutObject。…

VMware安装飞牛私有云fnOS并挂载小雅Alist实现异地远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

记一次键盘f2和f5键被自动触发情况

背景&#xff1a; 联想小新笔记本电脑内置键盘&#xff0c;其中f2键和f5键一直被自动触发&#xff0c;已尝试过更换输入法&#xff0c;重装系统&#xff0c;拆开键帽清灰依旧无效。考虑维修费或者更换键盘&#xff08;内置&#xff09;费都挺贵的&#xff0c;而且f2和f5作用也…

Unity教程(十六)敌人攻击状态的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

2024java面试-软实力篇

为什么说简历很重要&#xff1f; 一份好的简历可以在整个申请面试以及面试过程中起到非常好的作用。 在不夸大自己能力的情 况 下&#xff0c;写出一份好的简历也是一项很棒的能力。为什么说简历很重要呢&#xff1f; 、 先从面试来说 假如你是网申&#xff0c;你的简历必然…

论文阅读-《Attention is All You Need》

注意力就是一切 【要点】&#xff1a;论文提出了一种全新的网络架构——Transformer&#xff0c;完全基于注意力机制&#xff0c;无需使用循环和卷积&#xff0c;实现了在机器翻译任务上的性能提升和训练效率的显著提高。 【方法】&#xff1a;通过构建一个仅使用注意力机制的…

【计算机网络 - 基础问题】每日 3 题(十三)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

cadence SPB17.4 - allegro - 用板子外形创建整板铺铜

文章目录 cadence SPB17.4 - allegro - 用板子外形创建整板铺铜概述笔记先确定自己板子的 board Geometry/Design_Outline 是否有外形shape为了将软件提示看得更清楚&#xff0c;在每个操作之前&#xff0c;先将命令提示区内容先删了用Z-copy从外形层生成整板的铺铜备注END cad…

【JS】postMessage与MessageChannel

前言 postMessage 和 MessageChannel 都是用来实现跨文档、跨窗口或跨线程&#xff08;Web Worker&#xff09;的消息传递机制。 postMessage 可以在 iframe、同源或跨源窗口之间传递数据&#xff0c;也可以用于主线程与 Web Worker 之间的通信。 postMessage 是一种单向的…

数据结构-3.1.栈的基本概念

一.栈的定义&#xff1a; 栈和线性表的区别&#xff1a;栈只能在表尾一端进行插入或者删除的操作&#xff0c;而线性表可以在任意一个地方进行插入或者删除 二.有关栈的关键术语&#xff1a; 三.栈的基本操作&#xff1a; 1.回顾线性表的基本操作&#xff1a; 2.栈的基本操作&…

佰朔资本:国内海风加速招标 船舶行业景气上行

昨日&#xff0c;沪指盘中一度下探失守2700点&#xff0c;尾盘在地产、银行等板块的带动下发力上扬&#xff0c;深证成指亦翻红。到收盘&#xff0c;沪指涨0.49%报2717.28点&#xff0c;深证成指涨0.11%报7992.25点&#xff0c;创业板指跌0.11%报1533.47点&#xff0c;上证50指…

商业终端架构技术-未来之窗行业应用跨平台架构

未来之窗行业应用跨平台架构 以下是对未来之窗行业应用跨平台架构中客户端的稳定优势和网页跨平台性质的扩展列举&#xff1a; 一、客户端的稳定优势&#xff1a; 1. 离线可用性 - 即使在没有网络连接的…

如何将MySQL卸载干净(win11)

相信点进来的你肯定是遇到了这个问题&#xff0c;那就是在安装MySQL的时候操作错误&#xff0c;最后结果不是自己想要的。卸载重新安装又发现安装不了。其实最主要的原因就是没有将MySQL卸载干净&#xff0c;那么如何把MySQL卸载干净&#xff1f;下面本篇文章就来给大家一步步介…

Tiny-universe 1:Qwen整体介绍Qwen-blog

Qwen模型架构讲解直播&#xff1a;直播链接 Qwen的整体架构与Llama2类似&#xff0c;如下图所示: 其中: tokenizer将文本转为词表里面的数值。数值经过embedding得到一一对应的向量。attention_mask是用来看见左边、右边&#xff0c;双向等等来设定。各类下游任务&#xff0…

Kafka集群扩容(新增一台kafka节点)

kafka集群扩容、kafka topic迁移 现有环境 IP组件角色192.168.17.51kafka01broker1192.168.17.52kafka02broker2192.168.17.53kafka03broker3 扩容之后环境 IP组件角色192.168.17.51kafka01broker1192.168.17.52kafka02broker2192.168.17.53kafka03broker3192.168.17.54ka…

InternVL 微调实践闯关任务

基础任务 follow 教学文档和视频使用QLoRA进行微调模型&#xff0c;复现微调效果&#xff0c;并能成功讲出梗图. 尝试使用LoRA&#xff0c;或调整xtuner的config&#xff0c;如LoRA rank&#xff0c;学习率。看模型Loss会如何变化&#xff0c;并记录调整后效果(选做&#xff…

【论文串烧】多媒体推荐中的模态平衡学习 | 音视频语音识别中丢失导致的模态偏差对丢失视频帧鲁棒性的影响

文章目录 一、多媒体推荐中的模态平衡学习1.1 研究背景1.2 解决问题1.3 实施方案1.4 文章摘要1.5 文章重点1.6 文章图示图 1&#xff1a;不同模型变体在 AmazonClothing 数据集上的初步研究图 2&#xff1a;CKD模型架构的说明图 3&#xff1a;在 Amazon-Clothing 数据集上训练过…

【LabVIEW】事件结构的用法

本篇文章记录我学习LabVIEW的事件结构用法&#xff0c;希望我的分享对你有所帮助&#xff01; 目录 一、案例说明 1、 LabVIEW实现“YAXBXC的计算” 2、添加事件结构 一、案例说明 在LabVIEW实现“YAXBXC的计算”的基础上&#xff0c;加上事件结构&#xff0c;实现单击一次按…

后端接收数组,集合类数据

文章目录 一. 请求行Path参数&#xff08;不建议&#xff09;二.数组接收&#xff08;不建议&#xff09;三.List集合接收&#xff08;建议&#xff09;四. GET请求既包含请求体又包含请求行 一. 请求行Path参数&#xff08;不建议&#xff09; DeleteMapping("/{ids}&quo…