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

C语言第18节:自定义类型——联合和枚举

1. 联合体

C语言中的联合体(Union)是一种数据结构,它允许在同一内存位置存储不同类型的数据。不同于结构体(struct),结构体的成员各自占有独立的内存空间,而联合体的所有成员共享同一块内存区域。这意味着在同一时间,联合体中只能存储一个成员的值,其他成员会被覆盖。

1.1 联合体的基本语法

联合体的声明与结构体相似,使用关键字union来定义。

编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体。

一个简单的联合体例子如下:

#include <stdio.h>union Data {int i;float f;char str[20];
};int main() {union Data data;data.i = 10;printf("data.i = %d\n", data.i);data.f = 220.5;printf("data.f = %.2f\n", data.f);// 注意,data.i的值会被覆盖printf("data.i = %d\n", data.i); // 这个值会发生变化return 0;
}

在这里插入图片描述

1.2 联合体的内存分配与大小计算

在C语言中,联合体的所有成员都共享同一块内存区域。当你定义一个联合体时,它的内存空间并不会为每个成员分配独立的内存,而是为所有成员分配一块共享的内存区域。这样,联合体的内存大小至少等于成员中最大类型的成员大小

举个例子:

#include <stdio.h>union Data {int i;       // 4 字节float f;     // 4 字节char str[20]; // 20 字节
};int main() {printf("Size of union Data: %lu\n", sizeof(union Data));return 0;
}

解释:

  • int i 通常占用 4 字节。
  • float f 通常也占用 4 字节。
  • char str[20] 占用 20 字节(每个字符占 1 字节)。

由于联合体的成员共享内存,它的大小等于其中最大成员的大小。在这个例子中,char str[20] 的大小是 20 字节,因此联合体的大小会是 20 字节。换句话说,联合体的内存分配通常是由它的最大成员决定的,且内存中只能保存一个成员的数据。

输出:

Size of union Data: 20

1.2.1 联合体的内存对齐

除了最大成员的大小外,还要注意内存对齐(memory alignment)。C语言中,对于每个数据类型,通常都有对齐要求。具体对齐方式与系统架构、编译器有关(在C语言第17节:自定义类型——结构体已经讲过了,点击链接即可查看)。内存对齐的目的是为了提高访问效率,因此编译器往往会将数据类型按一定的字节边界对齐(例如,4字节对齐、8字节对齐等)。

内存对齐的示例:

假设我们使用的是32位或64位的架构,它可能要求对齐到4字节边界。我们来观察一下一个包含不同类型成员的联合体的内存分配。

// VS2022 MSVC
#include <stdio.h>union Example {char c;    // 1 字节int i;     // 4 字节double d;  // 8 字节
};int main() {printf("Size of union Example: %lu\n", sizeof(union Example));return 0;
}

解释:

  • char c 占用 1 字节。
  • int i 占用 4 字节。
  • double d 占用 8 字节。

但由于内存对齐的原因,联合体的实际大小可能会比这些单独成员的大小之和要大。通常,为了提高访问速度,编译器会插入一些填充字节(padding),使得联合体的内存大小是最大对齐数的倍数。

输出:

Size of union Example: 8

为什么是8字节呢?因为联合体中最大成员是double d,它的大小是8字节,而且对齐数也是8。因此,整个联合体的大小会是8字节。

1.2.2 联合体内存分配的详细说明

  1. 成员共享内存
    • 联合体中的所有成员共享同一块内存区域。在任何时刻,联合体的内存中只会保存一个成员的值。
    • 联合体的大小通常由最大成员的大小决定,因为它必须能够容纳最大成员的数据。
  2. 内存对齐
    • 编译器为了提高数据访问的效率,会根据平台的对齐要求插入填充字节(padding)。内存对齐确保数据按适当的字节边界存放(例如,4字节对齐、8字节对齐),从而使得CPU可以更快速地访问这些数据。
    • 在一些平台上,数据类型可能有特定的对齐要求。
  3. 联合体的大小计算
    • 联合体的大小通常等于其最大成员的大小,但是,为了满足内存对齐的要求,联合体的实际大小可能会大于最大成员的大小。它会被填充到最接近对齐要求的倍数。
    • 内存对齐填充通常是由编译器自动管理的,但了解这一点对于理解联合体的内存分配非常重要。

1.2.3 进一步的例子:多成员联合体与内存对齐

假设我们有一个更复杂的联合体,其中包含不同类型的数据,并且考虑到内存对齐的影响:

#include <stdio.h>union Complex {char c[21];    // 21 字节int i;         // 4 字节double d;      // 8 字节short s;       // 2 字节
};int main() {printf("Size of union Complex: %lu\n", sizeof(union Complex));return 0;
}

分析:

  • char c[21]:这是一个字符数组,它占用21字节(每个字符占1字节)。没有对齐要求
  • int i:整数类型,通常占用4字节。要求 4 字节对齐,即它会被存储在4字节对齐的位置。
  • double d:双精度浮点类型,通常占用8字节。要求 8 字节对齐,因此它会被存储在8字节对齐的位置。
  • short s:短整型,通常占用2字节。要求 2 字节对齐,它会被存储在2字节对齐的位置。

联合体的实际大小

  • 联合体的大小由最大对齐数决定。在这个例子中,最大成员是 double d(虽然 char c[21] 占用了 21 字节,但是其对齐数取决于存储的元素,即其对齐数为 char 的对齐数1),它的大小是 8 字节,其对齐数为 8 。因此,联合体的大小将是 8 字节的倍数。
  • 即使 char c[21] 占用了 21 字节,但联合体的总大小会由于对齐要求被填充到适合最大成员对齐的大小。

因此,联合体的实际大小会是 24 字节。 这是因为:

  • double d 会占用 8 字节,并且需要 8 字节对齐,因此联合体的总大小将被填充到最接近8字节对齐的倍数,即 24 字节。

1.2.4 总结

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

1.3 联合体的特点

  1. 共享内存:联合体的所有成员共享同一块内存区域,因此一个联合变量的大小,至少是最大成员的大小。

    例子:

    #include <stdio.h>union Data {int i;float f;char str[20];
    };int main() {union Data data;printf("&data:    %p\n", &data);printf("&data.i:  %p\n", &data.i);printf("&data.f:  %p\n", &data.f);printf("data.str: %p\n", data.str);return 0;
    }
    

    在这里插入图片描述

  2. 只能存储一个成员的值:每次只能访问联合体中的一个成员。给一个成员赋值时,其他成员的值会被覆盖。

  3. 节省内存空间:联合体在节省内存方面非常有用,尤其是当你需要存储多种不同类型的数据,但在任何时刻只需要其中一个类型的数据时。

    例子:

    #include <stdio.h>
    #include <string.h>
    union Data {int i;float f;char str[20];
    };int main() {union Data data;strcpy(data.str, "abcdefgh");data.i = 0x11223344;return 0;
    }
    

1.4 访问联合体成员

联合体成员可以通过.(点)操作符访问。例如:

union Data data;
data.i = 100;
printf("data.i = %d\n", data.i); // 输出100data.f = 98.6;
printf("data.f = %.2f\n", data.f); // 输出98.6

1.5 联合体的使用场景

1.5.1 场景①

在网络通信中,我们经常需要处理不同类型的数据包。这些数据包的内容可能会根据协议的不同而有所不同。例如,有些协议可能传输整数数据,有些可能传输浮动数数据,还有些可能传输字符串数据。在这种情况下,我们可以使用联合体来处理这些不同的数据格式。

场景描述:

假设你正在开发一个通信协议处理程序,该程序需要解析网络传输过来的数据包。每个数据包的类型和内容可能会有所不同,但在任何时刻,每个数据包只会包含一种类型的数据。为了节省内存,你可以使用联合体来存储不同类型的数据。

  1. 协议A 可能会传输一个 整数(比如用户ID)。
  2. 协议B 可能会传输一个 浮动数(比如温度传感器的数据)。
  3. 协议C 可能会传输一个 字符串(比如设备状态信息)。

通过联合体,你可以为这些数据包定义一个结构,使得它们共享同一块内存。每次你收到一个数据包时,根据协议类型,你可以决定是存储整数、浮动数,还是字符串,但内存中始终只有一种数据。

优势:

  • 节省内存:由于不同数据类型共享内存,只有在需要时,才会使用最大类型的内存(例如字符串可能占用更多的字节)。
  • 灵活性:能够处理不同协议的数据格式,只需要用一个联合体存储数据。

这个场景在 网络通信嵌入式系统文件格式解析 等领域非常常见,特别是在需要处理多种类型数据的系统中。

1.5.2 场景②

姓名性别年龄婚姻状况婚姻状况标记
未婚已婚离婚
结婚日期配偶姓名子女数量离婚日期子女数量
struct Person					// 定义职工个人信息结构体类型
{char name[20];				// 姓名char sex;					// 性别int age;					// 年龄union MaritalState marital; // 婚姻状况int marryFlag;				// 婚姻状况标记
};union MaritalState					// 定义婚姻情况共用体
{int single;						// 未婚struct MarriedState married;	// 已婚struct DivorceState divorce;	// 离婚
};struct MarriedState			// 定义已婚结构体类型
{struct Date marryDay;   // 结婚日期char spouseName[20];	// 配偶姓名int child;				// 子女数量
};struct DivorceState			// 定义离婚结构体类型
{struct Date divorceDay; // 离婚日期int child;				// 子女数量
};struct Date
{int year;short month;short day;
};

1.6 联合体判断大小端

int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是小端,返回0是大端
}

在C语言第16节:数据在内存中的存储已经讲过,这里不再赘述。

2. 枚举类型

C语言中的枚举类型(enum)是一种用户自定义的数据类型,用于表示一组具名的常量。枚举类型将一组相关的常量组合在一起,并赋予它们有意义的名字。使用枚举可以使程序的代码更加清晰、易于理解和维护。

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

性别有:男、女、保密,也可以一 一列举

月份有12个月,也可以一 一列举

三原色,也是可以一 一列举

2.1 枚举类型的基本语法

定义枚举类型的语法如下:

enum 枚举名 {常量1 =1,常量2 =2,常量3 =3,...
};
  • 枚举名 是枚举类型的名称。
  • 常量 是枚举中的各个值,通常是一些具名常量,默认情况下,枚举常量从 0 开始,依次递增,除非你为它们指定了不同的值。

2.1.1 例子:基本枚举类型

#include <stdio.h>enum Day {Sunday,    // 默认值为 0Monday,    // 默认值为 1Tuesday,   // 默认值为 2Wednesday, // 默认值为 3Thursday,  // 默认值为 4Friday,    // 默认值为 5Saturday   // 默认值为 6
};int main() {enum Day today;today = Wednesday;  // today 被赋值为 3printf("Today is day number: %d\n", today);  // 输出:Today is day number: 3return 0;
}

2.2 枚举常量的默认值

如果你没有为枚举常量指定值,默认情况下,第一个常量的值为 0,后续常量的值依次递增 1。例如,在上面的代码中,Sunday 默认值为 0,Monday 为 1,依此类推。

2.3 枚举常量的自定义值

你可以手动为枚举常量指定值。这意味着你可以设置任意值,而不依赖于默认的递增规则。

#include <stdio.h>enum Day {Sunday = 1,    // 设定为 1Monday = 2,    // 设定为 2Tuesday = 5,   // 设定为 5Wednesday = 7, // 设定为 7Thursday,      // 默认递增,从 8 开始Friday,        // 9Saturday       // 10
};int main() {enum Day today;today = Thursday;  // today 被赋值为 8printf("Today is day number: %d\n", today);  // 输出:Today is day number: 8return 0;
}

在这个例子中,SundayMonday 的值分别被设置为 1 和 2,而其他常量则从 Wednesday 开始自动递增。

2.4 枚举类型的实际应用

枚举常常用于表示一些固定的状态或选项,比如星期几、颜色、方向、状态码等。它能够使代码更加清晰,减少硬编码的数字。

2.4.1 例子:使用枚举表示交通信号灯的状态

#include <stdio.h>enum TrafficLight {Red,        // 0Yellow,     // 1Green       // 2
};int main() {enum TrafficLight signal;signal = Green;if (signal == Green) {printf("Go!\n");} else if (signal == Yellow) {printf("Caution!\n");} else {printf("Stop!\n");}return 0;
}

在这个例子中,TrafficLight 枚举表示了交通信号灯的三个状态:红灯、黄灯和绿灯。每个状态有一个默认的整数值:Red 为 0,Yellow 为 1,Green 为 2。通过这种方式,代码更易理解,避免了使用数字来表示信号灯的状态。

2.5 枚举类型的大小

在 C 语言中,枚举类型的大小与编译器的实现有关。通常,编译器会根据枚举常量的取值范围来决定枚举类型的存储大小。如果枚举的值在 int 类型的范围内,编译器通常会选择 int 类型来存储枚举值。但有些编译器可能根据需要进行优化,使用较小的存储类型。

可以使用 sizeof 来查看枚举类型的大小:

#include <stdio.h>enum Color {Red = 1,Green,Blue
};int main() {printf("Size of enum Color: %lu\n", sizeof(enum Color));  // 输出枚举类型的大小return 0;
}

2.6 枚举类型的转换

枚举常量本质上是整数,因此可以将它们转换为整数类型,或者将整数值赋给枚举变量。但要注意,这种做法可能会导致不符合预期的结果。

#include <stdio.h>enum Day {Sunday = 1,Monday = 2,Tuesday = 3
};int main() {enum Day today;today = 2;  // 可以将整数赋给枚举变量printf("Today is day number: %d\n", today);  // 输出:Today is day number: 2return 0;
}

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

2.7 枚举的优势

  • 提高代码可读性:枚举常量有具名的标识符,使代码更具语义。
  • 减少硬编码数字:避免了在代码中使用没有含义的数字常量。
  • 防止非法值:枚举确保变量只能取定义好的值。
  • 简化调试:具名常量方便在调试时辨识。
  • 增强维护性:修改枚举值时,只需要更改枚举定义,无需修改多个代码位置。
  • switch 语句结合使用:枚举常量使得 switch 语句的条件判断更加清晰。
  • 支持位域:与位运算结合使用,可以用来表示多个标志位。

—完—

相关文章:

C语言第18节:自定义类型——联合和枚举

1. 联合体 C语言中的联合体&#xff08;Union&#xff09;是一种数据结构&#xff0c;它允许在同一内存位置存储不同类型的数据。不同于结构体&#xff08;struct&#xff09;&#xff0c;结构体的成员各自占有独立的内存空间&#xff0c;而联合体的所有成员共享同一块内存区域…...

C++病毒(^_^|)(2)

第二期 声明&#xff1a; 仅供损害电脑&#xff0c;不得用于非法。损坏电脑&#xff0c;作者一律不负责。此作为作者原创&#xff0c;转载请经过同意。 直接上代码 #include <bits/stdc.h> #include <windows.h> using namespace std; HHOOK g_hHook;void lrud(…...

在vscode中拉取gitee里的项目并运行

拉取项目: 方法一:vscode点击查看--->终端(或者直接通过快捷键ctrol+ `打开) 在终端内通过cd命令定位到你想存放项目的文件夹 例如:cd h: 通过命令:git clone 地址 例如:git clone newbee-mall-vue-app: 前端代码 等待拉取完成即可在对应文件夹下看到项目啦 方…...

centos7 防火墙开放指定端口

在 CentOS 7 中&#xff0c;默认的防火墙管理工具是 firewalld。如果你想开放一个特定的端口&#xff0c;以便允许外部访问&#xff0c;可以通过以下步骤实现&#xff1a; 安装 firewalld 如果你的系统上还没有安装 firewalld&#xff0c;你可以通过以下命令安装&#xff1a; …...

Day42(补)【AI思考】-编译过程中语法分析及递归子程序分析法的系统性解析

文章目录 编译过程中语法分析及递归子程序分析法的系统性解析**一、总览&#xff1a;编译流程中的语法分析****1. 编译过程核心步骤** **二、语法分析的核心任务****1. 核心目标****2. 现实类比** **三、递归子程序分析法的本质****1. 方法分类****2. 递归子程序分析法的运作原…...

AI成为基础设施有哪些研究方向:模型的性能、可解释性,算法偏见

AI成为基础设施有哪些研究方向 模型的性能、可解释性和降低训练成本 伦理问题:算法偏见、数据隐私保护、人工智能的权利和责任 数据使用问题:公开数据已经使用完了,未来使用隐私数据(专家) 当AI成为基础设施后,研究方向将更加多元化和深入,涵盖技术创新、应用拓展、…...

写一个鼠标拖尾特效

思路和逻辑 要实现鼠标拖尾特效&#xff0c;我们需要&#xff1a; 监听鼠标移动事件&#xff0c;获取鼠标的当前位置。在每次鼠标移动时&#xff0c;绘制一个小圆点或其他形状在鼠标的当前位置。将所有绘制的圆点连接起来&#xff0c;形成一条“尾巴”。使用动画效果让尾巴看…...

Redisson介绍和入门使用

一、什么是Redisson&#xff1f; Redisson是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅提供了一系列的分布式的Java常用对象&#xff0c;还提供了许多分布式服务&#xff0c;其中就包含了各种分布式锁的实现。 官网地址…...

OpenAI推出全新AI助手“Operator”:让人工智能帮你做事的新时代!

引言 随着人工智能技术的不断发展&#xff0c;OpenAI 再次推出令人兴奋的功能——Operator&#xff0c;一个全新的 AI 助手平台。这不仅仅是一个普通的助手&#xff0c;它代表了人工智能技术的又一次飞跃&#xff0c;将改变我们工作和生活的方式。 什么是“Operator”&#xff…...

Python----PyQt开发(PyQt基础,环境搭建,Pycharm中PyQttools工具配置,第一个PyQt程序)

一、QT与PyQT的概念和特点 1.1、QT QT是一个1991年由The Qt Company开发的跨平台C图形用户界面应用程序开发 框架&#xff0c;可构建高性能的桌面、移动及Web应用程序。也可用于开发非GUI程序&#xff0c;比如 控制台工具和服务器。Qt是面向对象的框架&#xff0c;使用特殊的代…...

算法笔记 02 —— 入门模拟

本系列为胡凡编著的算法笔记当中代码部分的精简版整理&#xff0c;笔者也在同时准备Leetcode刷题和实习面试&#xff0c;希望为有一定编码和数据结构基础的同学提供一份系统型的参考&#xff0c;以方便遗忘时的算法查阅、期末复习总览以及C学习参照。 目录 01 简单模拟 Ⅰ害…...

PyTorch 源码学习:从 Tensor 到 Storage

分享自己在学习 PyTorch 源码时阅读过的资料。本文重点关注 PyTorch 的核心数据结构 Tensor 的设计与实现。因为 PyTorch 不同版本的源码实现有所不同&#xff0c;所以笔者在整理资料时尽可能按版本号升序&#xff0c;版本号见标题前[]。最新版本的源码实现还请查看 PyTorch 仓…...

uniapp 使用 鸿蒙开源字体

uniapp vue3 使用 鸿蒙开源字体 我的需求是全局使用鸿蒙字体。 所以&#xff1a; 0. 首先下载鸿蒙字体&#xff1a; 鸿蒙资源 下载后解压&#xff0c;发现里面有几个文件夹&#xff1a; 字体名称说明Sans默认的鸿蒙字体&#xff0c;支持基本的多语言字符&#xff08;包括字…...

LabVIEW多电机CANopen同步

核心问题与解决方案 通信层配置 节点ID与波特率冲突问题&#xff1a;在多电机系统中&#xff0c;节点ID重复或波特率不匹配常导致通信中断或数据丢失。案例&#xff1a;某3轴贴片机因步科驱动器的默认节点ID均为1&#xff0c;触发了总线仲裁错误。解决方案&#xff1a;通过配置…...

每日定投40刀BTC(2)20250209 - 20250212

行路吟 青山叠叠水迢迢&#xff0c; 步履虽艰志未消。 莫问前程几多苦&#xff0c; 长风破浪自逍遥。...

【LeetCode Hot100 子串】和为 k 的子数组、滑动窗口最大值、最小覆盖子串

子串 1. 和为 k 的子数组题目描述解题思路主要思路步骤 时间复杂度与空间复杂度代码实现 2. 滑动窗口最大值题目描述解题思路双端队列的原理&#xff1a;优化步骤&#xff1a; Java实现 3. 最小覆盖子串题目描述解题思路滑动窗口的基本思路&#xff1a;具体步骤&#xff1a;算法…...

某虚拟页式存储管理系统中有一个程序占8个页面,运行时访问页面的顺序是1,2,3,4,5,3,4,1,6,7,8,7,8,5。假设刚开始内存没有预装入任何页面。

某虚拟页式存储管理系统中有一个程序占8个页面&#xff0c;运行时访问页面的顺序是1,2,3,4,5,3,4,1,6,7,8,7,8,5。假设刚开始内存没有预装入任何页面。 (1) 如果采用LRU调度算法&#xff0c;该程序在得到4块内存空间时&#xff0c;会产生多少次缺页中断&#xff1f;请给出详细…...

傅里叶公式推导(三)

文章目录 周期 2L周期T 周期 2L 周期 T 2 L T2L T2L 的傅里叶变换 即 f ( t ) f ( t 2 L ) f(t) f(t2L) f(t)f(t2L) xt2 π \pi π 2 L 2L 2L 原公式 f ( x ) a 0 2 ∑ n 1 ∞ [ a n cos ⁡ n x b n sin ⁡ n x ] a 0 1 π ∫ − π π f ( x ) d x a n 1 π ∫…...

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_time_update函数

定义在 src\core\ngx_times.c 中 ngx_time_init 函数后面 void ngx_time_update(void) {u_char *p0, *p1, *p2, *p3, *p4;ngx_tm_t tm, gmt;time_t sec;ngx_uint_t msec;ngx_time_t *tp;struct timeval tv;if (!ngx_trylock(&ngx…...

老牌系统工具箱,现在还能打!

今天给大家分享一款超实用的电脑软硬件检测工具&#xff0c;虽然它是一款比较“资深”的软件&#xff0c;但依然非常好用&#xff0c;完全能满足我们的日常需求。 电脑软硬件维护检测工具 功能强大易用 这款软件非常贴心&#xff0c;完全不需要安装&#xff0c;直接打开就能用…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...