当前位置: 首页 > news >正文

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

自定义类型

  • 结构体
    • 结构体的声明
    • 特殊的声明
    • 结构的自引用
    • 结构体变量的定义和初始化
    • 结构体内存对齐
    • 修改默认对齐数
      • offsetof宏
    • 结构体传参
  • 位段
    • 位段的定义(声明)
    • 位段的内存分配
    • 位段的跨平台问题
    • 位段的应用
  • 枚举
    • 枚举类型的定义及使用
    • 枚举的优点
  • 联合(共用体)
    • 联合类型的定义
    • 联合的特点
    • 联合大小的计算

结构体

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

结构体的声明

struct tag
{member-list;
}variable-list;struct——关键字
tag——结构体的标签名
struct tag——结构体类型名
member-list——成员列表(成员变量的列表)
variable-list——变量列表

实例一(描述一本书):

struct Book
{char name[20];int price;char id[12];
}b4,b5,b6;//b4,b5,b6是全局的int main()
{//b1,b2,b3是局部变量struct Book b1;struct Book b2;struct Book b3;return 0;
}

特殊的声明

在声明结构的时候,可以不完全的声明。

实例一:

//匿名结构体类型
//两个结构在声明的时候省略掉了结构体标签(tag)
struct
{int a;char b;float c;
}x;
struct
{int a;char b;float c;
}a[20], *p;int main()
{p=&x;//会报警告//注:在编译器看来虽然结构体中的成员是一模一样的,但编译器仍然认为这两个结构体是不同的类型(在编译器看来是不合理的)return 0;
}

注:匿名结构体类型创建好之后只能用一次(没有标签构不成结构体类型)

结构的自引用

实例一:


struct Node
{int data;struct Node next;
};
//不可以这样定义(这样会死递归的)

注:在结构中包含一个类型为该结构本身的成员是不可以的

结构体自引用:

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

注:

  • 数据结构是数据在内存中存储的结构
  • 线性数据结构:顺序表、链表;树形数据结构:二叉树
  • 链表中的节点分为两部分数据域(存储的是数据)和指针域(存放的是下一个节点的地址)

总结:结构体自引用不是包含同类型的结构体变量而是包含同类型的结构体的指针

实例二:

typedef struct
{int data;Node* next;
}Node;
//这样写代码,是错误的
//先有Node*定义出的成员才能对类型进行重命名产生Node(陷入先有蛋还是先有鸡的问题)//解决方案:
typedef struct Node
{int data;struct Node* next;  //重命名的Node不能在成员里用
}Node;

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

实例一:

struct Point
{int x;int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};struct Stu        //类型声明
{char name[15];//名字int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化struct Node
{int data;struct Point p;struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

实例二:

struct S
{char c;int i;
}s1, s2;struct B
{double d;struct S s;char c;
};
int main()
{struct S s3 = {'x', 20};struct B sb = { 3.14, {'w', 100},'q' };//. //->printf("%lf %c %d %c\n", sb.d, sb.s.c, sb.s.i, sb.c);return 0;
}

注:

  • 结构体不完全初始化时其余没初始化的默认赋值0
  • 结构体是直接可以赋值的

结构体内存对齐

实例一:

#include<stdio.h>
struct S
{char c;int i;char c2;
};
int main()
{struct S s = { 0 };printf("%d\n", sizeof(s));return 0;
}

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

结构体的对齐规则:

  • 第一个成员在与结构体变量偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
  • 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

注:

  • 偏移量是结构体变量中成员的地址和结构体变量地址之差(偏移量是相对于结构体起始位置的偏移量)。
  • VS默认对齐数为8,linux无对齐数(即该成员的字节大小为对齐数)
  • 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
  • 对于Linux中GCC编译器对齐数就是该成员的大小

实例二:

#include <stdio.h>struct S4
{double d;char c;int i;
};
struct S5
{char c1;struct S4 s4;double d;
};int main()
{struct S5 s5 = {0};printf("%d\n", sizeof(s5));  //32return 0;
}

解析:
在这里插入图片描述

为什么存在内存对齐?

大部分的参考资料都是如是说的:

  • 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

总体来说:结构体的内存对齐是拿空间来换取时间的做法。

在设计结构体的时候,既要满足对齐,又要节省空间。可以通过**让占用空间小的成员尽量集中在一起。**从而达到节省空间的目的

实例三:

在这里插入图片描述

在这里插入图片描述

可以看出两个结构体的成员相同,但顺序不同,从而结构体所占内存的大小也就不同

修改默认对齐数

#pragmg pack(N) //设置默认对齐数为N

实例一:

#include<stdio.h>
//默认对齐数是8
//把默认对齐数改为2
#pragma pack(2)
struct S
{char c1;        //结构体S按照默认对齐数为2进行内存对齐int i;char c2;
};
#pragma pack()  //取消设置的默认对齐数,还原为默认
int main()
{struct S s = { 0 };printf("%d\n", sizeof(s));return 0;
}

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

注:

  • 设置默认对齐数时一般设置成2^n,几乎不会设置成奇数
  • #pragma pack(1)将默认对齐数设置成1,不存在结构体的内存对齐
  • 修改默认对齐数的意义是结构在对齐方式不合适的时候,程序员可以自己更改默认对齐数

offsetof宏

offsetof是C语言本身具有的宏,用于计算结构体中某个成员相较于这个结构体变量起始位置的偏移量。
在这里插入图片描述

offsetof宏的使用

在这里插入图片描述

结构体传参

实例一:

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;
}

注:printf1函数和printf2函数的功能一样,但是printf2函数要比printf1函数的性能要好(时间和空间消耗较低)。原因是函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。因此结构体传参的时候,要传结构体的地址

位段

位段是依附于结构体的

位段的定义(声明)

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是 int、unsigned int 或signed int或char。
  2. 位段的成员名后边有一个冒号和一个数字

位段的定义:

struct A   //A就是一个位段类型
{int _a:2;int _b:5;int _c:10;int _d:30;
};

位段的内存分配

实例一:

struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 30;};
int main()
{printf("%d\n", sizeof(struct A));return 0;
}

在这里插入图片描述
注::冒号后+数字是占多少个比特位。

分析

struct A
{//4个字节-32bitint _a : 2;//成员占2个bit位int _b : 5;//成员占5个bit位int _c : 10;//成员占10个bit位//4个字节-32bitint _d : 30;//成员占30个bit位  //int _d : 30;中的_d位段成员在内存中开辟30个比特位是用之前开辟完剩余的比特位和新开辟的32位比特位还是只用新开辟的32位比特位,这是不确定的。因为C语言没有明确规定到底用不用前面的空间。
};
int main()
{printf("%d\n", sizeof(struct A));//4+4=8return 0;
}

位段的内存分配

  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;
};
int main()
{struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

分析( 该分析只适用于VS )
在这里插入图片描述

在这里插入图片描述

注:

  • 在VS编译器下一个字节(四个字节)内部的数据在使用时先使用低比特位的数据再使用高比特位的数据(从右向左使用)
  • 当一块空间剩余的空间内容不够下一个成员使用的时候这块空间会浪费掉

位段的跨平台问题

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

补充:

  • 在16位机器下整型类型占2个字节;在32位机器下整型类型占4个字节

总结:跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。

位段的应用

IP数据报的格式

在这里插入图片描述

枚举

枚举是把可能的取值一一列举。
枚举是创造新的类型,这种类型取值是非常有限的(明确的几种取值),这时可以用枚举创造枚举类型

枚举类型的定义及使用

实例一:

//声明枚举类型enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};enum Sex//性别
{MALE,FEMALE,SECRET
}enum Color//颜色
{RED,GREEN,BLUE
};

实例二:

enum Color  //enum枚举关键字  Color枚举的类型
{RED,  GREEN,    //枚举类型的可能取值   这些都是枚举常量BLUE
};
int main()
{enum Color c = BLUE;   //在C++中可以这样写enum Color c = Color::BLUE; ::(限定符),BLUE来自于Colorreturn 0;
}

注:

  • 枚举类型是用来描述那些能够把值一一确定出来的有限的几种值的类型的一种描述枚举,而结构体是为了描述复杂对象的。
  • 枚举类型是一种类型
  • 枚举那些可能取值的值的数值是整型

要点:

  • {}中的内容是枚举类型的可能取值,也叫枚举常量 。
  • 这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。

实例三:

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

注:

  • 不能写成enum Color c=2;在C++编译器中语法是不支持的(int类型无法转换成enum Color类型)类型不匹配
  • 枚举常量不能修改,但可以赋初值

实例四:

//声明枚举类型
enum Color
{RED=5,//5GREEN=8,//8BLUE//9
};int main()
{enum Color c = BLUE;printf("%d\n", sizeof(c));  //4//计算枚举类型的大小时它只有一种可能取值,所以它的大小就是整形大小return 0;
}

注:枚举类型所占内存的大小恒为4

枚举的优点

枚举与#define 定义常量的区别:

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

注:调试代码是在生成可执行程序之后,运行代码时才可以进行一定的调试

联合(共用体)

联合类型的定义

联合也是一种特殊的自定义类型。这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

联合类型的声明、定义:

//联合类型的声明
union Un 
{ char c; int i; 
}; //联合变量的定义
union Un un; //计算联合变量的大小
printf("%d\n", sizeof(un));

实例一:

union Un
{char c;//1int i;//4
};
int main()
{union Un u = {10};//union Un u = { 10,1000 };  //err  联合体多个成员共用一块空间初始化时不可能对多个成员进行初始化,其实只初始化一个成员u.i = 1000;u.c = 100;printf("%p\n", &u);printf("%p\n", &(u.c));printf("%p\n", &(u.i));printf("%d\n", sizeof(u));  //4return 0;
}

在这里插入图片描述

注:联合体在同一时间只能使用它其中的一个成员

实例二:

在这里插入图片描述

在这里插入图片描述

注:联合体初始化时会对联合体第一个成员进行初始化

联合的特点

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

实例一:

在这里插入图片描述

经典面试:

判断当前计算机的大小端存储

//判断当前计算机的大小端存储int check_sys1()
{int a = 1;if ((*(char*)&a) == 1){return 1;//小端}else{return 0;//大端}
}int check_sys2()
{union U{char c;int i;}u;u.i = 1;return u.c;//返回1 就是小端//返回0 就是大端
}int main()
{int ret = check_sys2();if (ret == 1)printf("小端\n");elseprintf("大端\n");return 0;
}

联合大小的计算

联合体大小计算规则:

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

实例一:

union Un
{char a[5];//对齐数1(相当于放了5个字符类型的变量)    int i;//对齐数4};int main()
{union Un u;printf("%d\n", sizeof(u));  //8return 0;
}

实例二:

union Un
{	short s[5];//对齐数2 int a;//对齐数4
};int main()
{union Un u;printf("%d\n", sizeof(u)); //12return 0;
}

相关文章:

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

自定义类型 结构体结构体的声明特殊的声明结构的自引用结构体变量的定义和初始化结构体内存对齐修改默认对齐数offsetof宏 结构体传参 位段位段的定义&#xff08;声明&#xff09;位段的内存分配位段的跨平台问题位段的应用 枚举枚举类型的定义及使用枚举的优点 联合&#xff…...

Node.js博客项目开发思路笔记

博客项目介绍 1. 目标 开发一个博客系统&#xff0c;具备博客基本功能只开发 server 端&#xff0c;不关心前端 2. 需求 首页、作者页、博客详情页登陆页管理中心、新建页、编辑页 3. 技术方案 数据如何存储 博客 idtitlecontentcreatetimeauthor1标题 1内容 11111112z…...

python 之 shutil 文件的复制、删除、移动文件以及目录,并支持文件的归档、压缩和解压

一、shutil shutil 模块于文件和文件集合的高级操作&#xff0c;包括&#xff1a;复制、删除、移动文件以及目录&#xff0c;并支持文件的归档、压缩和解压等 二、使用例子 复制文件及权限 shutil.copy(src, dst)复制文件及权限&#xff1b;src 和 dst 文件路径。dst 文件名或…...

jface

JFace 是建立在 SWT 之上的 UI 部件&#xff0c;它是 SWT 的扩展并能和SWT交互。 ApplicationWindow和Action org.eclipse.jface.window.ApplicationWindow; JFace为了简化窗口的设计特别设计了类&#xff0c;比如ApplicationWindow这一个类&#xff0c;它里面包含了六个默认…...

六级备考28天|CET-6|听力第一讲|基本做题步骤与方法|13:30~14:30

目录 1. 重点词汇 proofread / ˈpruːfriːd / v.校对&#xff0c;校阅 autonomous adj.独立的 obsession n. 喜好 ample …...

系统设计 - 设计一个速率限制器

实施速率限制器的位置主要取决于我们的应用程序、技术栈、技术团队等因素。通常有三个位置可供选择&#xff1a;客户端、服务器端或中间件。 客户端是不可靠的地方来执行速率限制&#xff0c;因为恶意行为者可以轻易伪造客户端请求。 比将速率限制器放在服务器端更好的方法是使…...

[技术分享]Android平台实时音视频录像模块设计之道

实现背景 录像有什么难的&#xff1f;无非就是数据过来&#xff0c;编码保存mp4而已&#xff0c;这可能是好多开发者在做录像模块的时候的思考输出。是的&#xff0c;确实不难&#xff0c;但是做好&#xff0c;或者和其他模块有非常好的逻辑配合&#xff0c;确实不容易。 好多…...

JDKMissionControl官方用户指南--人工翻译

1. JMC8新增功能 暂时用不到&#xff0c;暂略 2. JDK Mission Control是什么 JMC是一组高级工具&#xff0c;用于管理、监视、分析Java应用程序并排除其故障。JMC能够对代码性能、内存和延迟等领域进行高效而详细的数据分析&#xff0c;而不会引入通常与分析和监控工具相关的…...

MySql-高级(分库分表问题简析) 学习笔记

文章目录 1. 为什么要分库分表&#xff1f;2. 用过哪些分库分表中间件&#xff1f;不同的分库分表中间件都有什么优点和缺点&#xff1f;3. 你们具体是如何对数据库如何进行垂直拆分或水平拆分的&#xff1f;4. 分库分表时&#xff0c;数据迁移方案5. 如何设计可以动态扩容缩容…...

【5.20】五、安全测试——安全测试工具

目录 5.4 常见的安全测试工具 1. Web漏洞扫描工具——AppScan 2. 端口扫描工具——Nmap 3. 抓包工具——Fiddler 4. Web渗透测试工具——Metasploit 小提示&#xff1a;Kali Linux 5.4 常见的安全测试工具 安全测试是一个非常复杂的过程&#xff0c;测试所使用到的工具也…...

【13900k】i9 核显升级驱动

这里写自定义目录标题 官方的助手不能用显卡控制中心提示最新的更新搜索显卡 intel uhd graphics 770 手动下载安装自定义音频为啥也要卸载&#xff1f;新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片…...

使用Python将绿色转换为红色、红色转换为蓝色的图像处理

使用Python将绿色转换为红色、红色转换为蓝色的图像处理 在图像处理中&#xff0c;我们经常需要对图像进行颜色转换和修改。本篇博客介绍了如何使用Python的Pillow库来读取一个文件夹中的所有图像&#xff0c;并将其中的绿色转换为红色&#xff0c;红色转换为蓝色。我们还展示…...

Web2与Web3开发的不同之处

Web2是引入交互功能的第二代互联网&#xff0c;也是我们今天所熟悉的。随着Web的不断发展&#xff0c;第三代互联网&#xff0c;也被称为Web3&#xff0c;正处于积极开发中。Web3引入了在区块链上运行的去中心化和无需许可的系统。但是Web2和Web3开发之间有什么区别呢&#xff…...

递增数组的判断【python实现】

有时候需要对某一组数组的数据进行判断是否 递增 的场景&#xff0c;比如我在开发一些体育动作场景下&#xff0c;某些肢体动作是需要持续朝着垂直方向向上变化&#xff0c;那么z轴的值是会累增的。同理&#xff0c;逆向考虑&#xff0c;递减就是它的对立面。 下面是查找总结到…...

在自定义数据上训练 YOLOv8 实例分割

图像分割是一个核心视觉问题,可以为大量用例提供解决方案。从医学成像到分析流量,它具有巨大的潜力。实例分割,即对象检测+分割,甚至更强大,因为它允许我们在单个管道中检测和分割对象。为此,Ultralytics YOLOv8 模型提供了一个简单的管道。在本文中,我们将对自定义数据…...

洛谷密钥被破解:加密安全面临新挑战

密钥管理是加密系统中非常重要的一环&#xff0c;它涉及到密钥的生成、存储、分发、管理和销毁等多个方面。在密码学中&#xff0c;密钥是保护数据隐私和安全性的核心因素之一&#xff0c;因此&#xff0c;确保密钥的安全和保密性显得尤为重要。在2016年举办的 CQOI 数论竞赛中…...

02 Android开机启动之BootLoader及kernel的启动

Android开机启动之BootLoader及kernel的启动 1、booloader的启动流程 第一阶段:硬件初始化,SVC模式,关闭中断,关闭看门狗,初始化栈,进入C代码 第二阶段:cpu/board/中断初始化;初始化内存以及flash,将kernel从flash中拷贝到内存中,执行bootm,启动内核 2、kernel的启…...

代码随想录算法训练营 Day 49 | 121.买卖股票的最佳时机,122.买卖股票的最佳时机 II

121.买卖股票的最佳时机 讲解链接&#xff1a;代码随想录-121.买卖股票的最佳时机 确定 dp 数组以及下标的含义&#xff1a; dp[i][0] 表示第 i 天持有股票所得最多现金dp[i][1] 表示第 i 天不持有股票所得最多现金 确定递推公式&#xff1a; 如果第 i 天持有股票即 dp[i][0]&…...

精炼计算机网络——数据链路层(一)

文章目录 前言3.1 数据链路和帧3.1.1 数据链路和帧3.1.2 三个基本问题 3.2 点对点协议PPP3.2.1 PPP协议的特点3.2.2 PPP协议3.2.3 PPP协议的工作状态 总结 前言 上篇文章&#xff0c;我们一同学完了物理层的全部内容&#xff0c;在本篇文章中&#xff0c;我们初步学习数据链路…...

猿创征文|Spring系列框架之面向切面编程AOP

⭐️前面的话⭐️ 本篇文章将介绍一种特别重要的思想&#xff0c;AOP&#xff08;Aspect Oriented Programming&#xff09;&#xff0c;即面向切面编程&#xff0c;可以说是OOP&#xff08;Object Oriented Programming&#xff0c;面向对象编程&#xff09;的补充和完善。 …...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...