C语言结构体,枚举,联合

news2024/9/28 11:21:49

系列文章目录

第一章 C语言基础知识

第二章 C语言控制语句

第三章 C语言函数详解

第四章 C语言数组详解

第五章 C语言操作符详解

第六章 C语言指针详解

第七章 C语言结构体详解

第八章 详解数据在内存中的存储

第九章 C语言指针进阶


文章目录

1. 结构体

1.1 声明结构体

2.2 自引用结构

1. 单链表

2. 双链表

3. 二叉树

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

2.4 结构体内存对齐

2.5 修改默认对齐数

2.6 结构体传参

1. 通过值传递结构体

2. 通过指针传递结构体

2. 位段

2.1 定义位段

2.2 位段的内存分配

3. 枚举

3.1 枚举类型的定义

3.2 使用枚举

4. 联合

4.1 联合类型的定义

4.2 使用联合

4.3 联合大小的计算


1. 结构体

1.1 声明结构体

struct Tag {
    type member1;
    type member2;
    ...
    type memberN;
};
  • struct:关键字,用于定义结构体。
  • Tag:结构体的标签(可选),可以用来声明该类型的变量。
  • member1, member2, ..., memberN:结构体成员,可以是任意数据类型,包括整型、浮点型、字符型、数组、甚至其他结构体。

代码示例:定义一个表示人的结构体:

struct Person {
    char name[50];
    int age;
    float height;
};

2.2 自引用结构

自引用结构是指在结构体定义中包含至少一个指向同类型结构体的指针。这个指针可以用来指向具有相同结构的其他实例,从而形成一个链式或树形结构。

示例:定义自引用结构体

链表结构,其中每个节点包含一个整数数据和指向列表中下一个节点的指针。

struct Node {
    int data;       // 存储的数据
    struct Node *next;  // 指向下一个节点的指针
};
1. 单链表

在单链表中,每个节点包含数据和一个指向下一个节点的指针。这种结构可以用来实现队列、栈或其他动态数据集合。

void printList(struct Node *node) {
    while (node != NULL) {
        printf("%d ", node->data);
        node = node->next;
    }
}
2. 双链表

在双链表中,每个节点除了有指向下一个节点的指针外,还有一个指向前一个节点的指针,允许在两个方向上遍历列表。

struct DNode {
    int data;
    struct DNode *prev;
    struct DNode *next;
};
3. 二叉树

在二叉树的实现中,每个节点包含数据和两个指向子节点的指针(左子节点和右子节点)。这种结构用于实现高效的搜索、插入和删除操作。

struct TreeNode {
    int value;
    struct TreeNode *left;
    struct TreeNode *right;
};

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

定义结构体类型

struct Person {
    char name[100];
    int age;
    float height;
};

定义结构体变量

struct Person person1;
//定义了一个名为 person1 的变量,其类型为 struct Person

初始化结构体变量

struct Person person1 = {"TENET", 20, 2};

初始化结构体数组

结构体数组可以在定义时初始化

struct Person team[2] = {
    {"TENET", 20, 2},
    {"VENOM", 21, 2.1}
};

动态初始化

结构体的初始化也可以在程序执行中进行,尤其是当结构体的值需要在运行时确定时.

struct Person person3;
strcpy(person3.name, "TENET");  // 使用 strcpy 来复制字符串
person3.age = 20;
person3.height = 2.1;

完整代码示例:

#include <stdio.h>

// 定义一个名为 Point 的结构体,包含两个整数成员:x 和 y
struct Point
{
    int x; // x坐标
    int y; // y坐标
} p1; // 在定义类型的同时,声明了一个 Point 类型的变量 p1

// 单独声明一个 Point 类型的变量 p2
struct Point p2;

// 初始化:定义变量的同时赋初值
struct Point p3 = {1, 2}; // 使用列表初始化的方式初始化 p3,将 x 设置为 1,y 设置为 2

// 定义一个名为 Stu 的结构体,包含一个字符数组和一个整数
struct Stu // 类型声明
{
    char name[15]; // 存储名字的字符数组
    int age;       // 存储年龄的整型
} s = {"zhangsan", 20}; // 定义并初始化 Stu 类型的变量 s

// 定义一个名为 Node 的结构体,该结构体嵌套了 Point 结构体并包含一个指向自己类型的指针
struct Node
{
    int data; // 存储一个整数数据
    struct Point p; // 嵌套一个 Point 结构体
    struct Node* next; // 指向下一个 Node 结构体的指针
} n1 = {10, {4,5}, NULL}, // 初始化 n1,设置 data 为 10, p 的 x 和 y 分别为 4 和 5,next 为 NULL
  n2 = {20, {5, 6}, NULL}; // 同样初始化 n2,数据设置类似但不同于 n1

int main() {
    // 打印 n1 和 n2 的内容以验证初始化是否成功
    printf("n1 data: %d, point: (%d, %d)\n", n1.data, n1.p.x, n1.p.y);
    printf("n2 data: %d, point: (%d, %d)\n", n2.data, n2.p.x, n2.p.y);

    return 0;
}

2.4 结构体内存对齐

为什么需要内存对齐

内存对齐的主要目的是为了优化数据访问速度。大多数硬件平台对特定类型的数据访问有最佳的自然边界。例如,某些处理器访问一个整型数(通常是4字节)更有效率,如果它位于一个4字节的边界上。如果数据没有对齐,处理器可能需要多次访问内存来读取或写入单个数据项,这会降低程序的性能。

结构体对齐的规则

每个结构体成员相对于结构体起始的偏移量应该是该成员大小的整数倍。例如,如果一个成员是4字节整数,则其偏移量应该是4的倍数。

结构体的总大小也应该是其最宽基本类型成员大小的整数倍。如果不是,编译器会在结构体的末尾添加填充字节(padding),使其总大小符合这一规则。总的来说,就是让占用空间小的成员尽量集中在一起。

结构体示例:

struct Example {
    char a;    // 1 字节
    int b;     // 4 字节
    char c;    // 1 字节
};

内存布局是:

  • char a 直接放在起始位置。
  • 为了确保 int b 对齐到4字节边界,编译器在 char a 后面添加3字节的填充。
  • int b 放在第4字节位置。
  • char c 放在 int b 后面,紧接着是额外的填充字节,以确保整个结构体的大小是4的倍数(如果需要的话)。

练习:

struct S1
{
    char c1; // 占用 1 字节
    int i;   // 占用 4 字节,但因为对齐需求,c1 后面会有 3 字节的填充
    char c2; // 占用 1 字节
};
printf("%d\n", sizeof(struct S1)); // 输出结构体大小
  • 内存对齐:int 类型通常需要按 4 字节对齐。因此,char c1 后会有 3 字节的填充,以使 int i 在 4 字节边界上对齐。
  • 总大小:1字节 (c1) + 3字节 (填充) + 4字节 (i) + 1字节 (c2) = 9字节。但整个结构体也可能要对齐到 4 字节边界,因此实际大小可能为 12 字节(取决于具体的编译器和平台设置)。
struct S2
{
    char c1; // 占用 1 字节
    char c2; // 紧接着 c1,占用 1 字节
    int i;   // 需要对齐到 4 字节边界,因此 c2 后有 2 字节填充
};
printf("%d\n", sizeof(struct S2)); // 输出结构体大小
  • 内存对齐:为了让 int i 对齐到 4 字节边界,char c2 后需要填充 2 个字节。
  • 总大小:1字节 (c1) + 1字节 (c2) + 2字节 (填充) + 4字节 (i) = 8字节。
struct S3
{
    double d; // 占用 8 字节
    char c;   // 占用 1 字节,后面需要 7 字节填充以对齐 `int`
    int i;    // 占用 4 字节,需要对齐到 4 字节边界
};
printf("%d\n", sizeof(struct S3)); // 输出结构体大小
  • 内存对齐:double 类型通常需要按 8 字节对齐。为了让 int i 对齐到 4 字节边界,char c 后需要 7 字节的填充。
  • 总大小:8字节 (d) + 1字节 (c) + 7字节 (填充) + 4字节 (i) = 20字节。
struct S4
{
    char c1;   // 占用 1 字节
    struct S3 s3; // 嵌套结构体 S3,前面有 7 字节填充
    double d;  // 占用 8 字节,按 8 字节对齐
};
printf("%d\n", sizeof(struct S4)); // 输出结构体大小
  • 内存对齐:struct S3 已经分析为需要 20 字节,且需要按 8 字节对齐。char c1 后需要填充 7 字节,以确保 struct S3 s3 正确对齐。
  • 总大小:1字节 (c1) + 7字节 (填充) + 20字节 (s3, 嵌套结构体的大小) + 8字节 (d) = 36字节。

2.5 修改默认对齐数

#pragma 这个预处理指令,可以改变默认对齐数。

#include <stdio.h>

#pragma pack(8) // 设置默认对齐数为 8
struct S1
{
    char c1; // 1 字节
    int i;   // 4 字节,但由于对齐设置为 8,c1 后将填充 7 字节,使 i 对齐到 8 字节边界
    char c2; // 1 字节,由于对齐设置,c2 后可能填充至 8 字节边界
};
#pragma pack() // 取消设置的默认对齐数,还原为默认

#pragma pack(1) // 设置默认对齐数为 1
struct S2
{
    char c1; // 1 字节
    int i;   // 4 字节,紧接 c1,无需添加填充
    char c2; // 1 字节,紧接 i
};
#pragma pack() // 取消设置的默认对齐数,还原为默认

int main()
{
    // 输出结构体的大小
    printf("%d\n", sizeof(struct S1)); // 根据对齐规则和成员定义,预期的大小
    printf("%d\n", sizeof(struct S2)); // 根据对齐规则和成员定义,预期的大小
    return 0;
}

对于 struct S1,其对齐设置为 8 字节:

  • char c1 占用 1 字节,后面紧跟 7 字节填充,使得 int i 对齐到下一个 8 字节边界。
  • int i 占用 4 字节。
  • char c2 占用 1 字节,可能跟随 7 字节的填充,以确保整个结构体的大小为最大成员对齐(8 字节的倍数)。
  • sizeof(struct S1) 通常为 16 字节(1 字节 c1 + 7 字节填充 + 4 字节 i + 1 字节 c2 + 3 字节填充以达到8的倍数)。

对于 struct S2,其对齐设置为 1 字节:

  • char c1 占用 1 字节。
  • int i 紧接 c1,占用 4 字节,不需要填充因为对齐要求已经是 1 字节。
  • char c2 紧接 i,占用 1 字节。
  • 因此,sizeof(struct S2) 为 6 字节(1 字节 c1 + 4 字节 i + 1 字节 c2)。

2.6 结构体传参

1. 通过值传递结构体

当结构体通过值传递给函数时,实际上是传递结构体的一个副本。这意味着函数内部对结构体成员的任何修改都不会影响原始结构体。

代码示例

#include <stdio.h>

struct Point {
    int x, y;
};

// 函数接收结构体副本
void movePoint(struct Point p) {
    p.x += 1;
    p.y += 1;
    printf("Inside function: x = %d, y = %d\n", p.x, p.y);
}

int main() {
    struct Point pt = {10, 20};
    movePoint(pt);  // 传递副本
    printf("Outside function: x = %d, y = %d\n", pt.x, pt.y);  // 原始数据未改变
    return 0;
}

2. 通过指针传递结构体

当结构体通过指针传递给函数时,传递的是结构体的地址,允许函数直接访问并修改原始结构体的数据。

代码示例:

#include <stdio.h>

struct Point {
    int x, y;
};

// 函数接收结构体指针
void movePoint(struct Point *p) {
    p->x += 1;
    p->y += 1;
    printf("Inside function: x = %d, y = %d\n", p->x, p->y);
}

int main() {
    struct Point pt = {10, 20};
    movePoint(&pt);  // 传递指针
    printf("Outside function: x = %d, y = %d\n", pt.x, pt.y);  // 数据已被修改
    return 0;
}

2. 位段

位段(Bit-fields)是一种数据结构,用于访问结构体中的对象的指定数目的位。

位段的声明和结构是类似的,但有两个不同:
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字。

2.1 定义位段

位段在结构体中定义,每个位段成员后面需要指定它所占用的位数。位段的声明通常涉及一个整数类型(如 int、unsigned int 或 signed int),后面紧跟冒号和位数。

struct TEST {
    unsigned int a : 1;  // 占用 1 位
    unsigned int d : 5;  // 填充 5 位
};
// TEST是一个位段类型

2.2 位段的内存分配

位段是连续存储的,并尽可能紧凑地放在一起,但它们的布局和总占用空间大小依赖于特定的编译器实现和对齐规则。

代码示例:

struct S
{
    char a:3;  // 定义一个位段 a,占用 3 位
    char b:4;  // 定义一个位段 b,占用 4 位
    char c:5;  // 定义一个位段 c,占用 5 位
    char d:4;  // 定义一个位段 d,占用 4 位
};
struct S s = {0};  // 使用列表初始化将所有位段初始化为 0
s.a = 10;  // 给位段 a 赋值为 10
s.b = 12;  // 给位段 b 赋值为 12
s.c = 3;   // 给位段 c 赋值为 3
s.d = 4;   // 给位段 d 赋值为 4
  • 位段定义:a, b, c, 和 d 分别占用 3, 4, 5, 和 4 位。尽管它们被定义为 char 类型,这仅仅意味着这些位段是从一个 char 类型的存储单元中分配的,实际上它们占用的是指定的位数。
  • 初始化:初始化时,所有位段被设为 0。这是通过 {0} 完成的,确保结构体开始时所有位都是清零的。
  • 赋值:之后,为每个位段赋予了一个新值。注意赋值时要考虑位段的溢出。例如,a:3 表示 a 可以存储的最大值是 23−1=723−1=7(因为是无符号值)。因此,赋值 10 实际存储的是 10 % 8 = 2。

3. 枚举

3.1 枚举类型的定义

枚举就是把可能的取值一一列举,枚举通过关键字 enum 定义。枚举的定义会创建一个新的数据类型名称,可以列举出所有可能的枚举值。每个枚举值都是一个整数(通常是 int 类型),默认从 0 开始,每个后续的值递增 1。你也可以显式指定枚举值的数值。
enum enum_name {
    constant1,
    constant2,
    constant3,
    ...
};

示例:定义一个枚举

enum Day {
    Sunday,    // 默认为 0
    Monday,    // 默认为 1
    Tuesday,   // 默认为 2
    Wednesday, // 默认为 3
    Thursday,  // 默认为 4
    Friday,    // 默认为 5
    Saturday   // 默认为 6
};

也可以指定特定的数值:

enum Day {
    Sunday = 1,
    Monday,
    Tuesday = 5,
    Wednesday,
    Thursday = 10,
    Friday,
    Saturday
};

在这个例子中,Monday 将自动被赋值为 2(因为它紧跟在值为 1 的 Sunday 后面),Wednesday 为 6(紧跟在值为 5 的 Tuesday 后面),Friday 为 11(紧跟在值为 10 的 Thursday 后面)。

3.2 使用枚举

枚举类型可以用来声明变量。这些变量可以存储任何在枚举中定义的值:

enum Day today;
today = Monday;

if (today == Monday) {
    printf("Start of work week.\n");
}

枚举与整数的关系

枚举在 C 语言中本质上是整数。你可以在不进行显式类型转换的情况下,将枚举值赋给整数变量:

int day = today;        
enum Day tomorrow = 3;  // 隐含星期四,如果从星期日开始 = 0

4. 联合

4.1 联合类型的定义

联合(共用体)是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。联合可以包含多个不同类型的成员,但任何时候只能存储其中一个成员的值。

联合通过关键字 union 定义,与结构体定义相似。联合体的定义创建了一个可以存储多个不同类型数据,但每次只能使用其中一个的数据类型。

union UnionName {
    type1 member1;
    type2 member2;
    type3 member3;
    ...
};

代码示例:

定义一个联合,这个联合可以用来存储整数、浮点数和字符指针。不管哪种类型的数据被存储,它们都使用同一块内存区域。

union Data {
    int i;
    float f;
    char *str;
};

4.2 使用联合

联合的使用类似于结构体,但需要记住的关键是联合存储的是同一块内存区域。因此,更改一个成员的值将影响到其他成员。

#include <stdio.h>

// 定义一个联合 Data,可以存储一个整数、一个浮点数或一个字符指针
union Data {
    int i;    // 可存储整数
    float f;  // 可存储浮点数
    char *str; // 可存储字符指针
};

int main() {
    union Data data;  // 声明一个 Data 类型的联合变量

    data.i = 10;  // 将整数 10 存储在联合的内存中
    printf("data.i : %d\n", data.i);  // 打印整数字段,输出 "data.i : 10"

    data.f = 220.5;  // 将浮点数 220.5 存储在同一块内存中,这会覆盖之前存储的整数
    printf("data.f : %.1f\n", data.f);  // 打印浮点数字段,输出 "data.f : 220.5"
    printf("data.i (corrupted) : %d\n", data.i);  // 再次打印整数字段,但由于内存已被浮点数覆盖,输出的值是未定义的(corrupted)

    data.str = "Hello World";  // 将字符串 "Hello World" 的指针存储在同一块内存中,这会覆盖之前存储的浮点数
    printf("data.str : %s\n", data.str);  // 打印字符串字段,输出 "data.str : Hello World"
    printf("data.f (corrupted) : %.1f\n", data.f);  // 再次打印浮点数字段,但由于内存已被字符串指针覆盖,输出的值也是未定义的(corrupted)

    return 0;
}

联合 Data 允许其成员 i、f 和 str 共享同一内存区域。该内存区域的大小等于其最大成员的大小,这里是 float 或 char*(具体取决于平台,通常这两种类型在现代架构上大小相同,都是 4 或 8 字节)。

当联合的一个成员被赋值时,它会覆盖联合内存中的当前内容。如果随后访问同一联合的另一个成员,得到的将是一个不确定的值,这是因为存储的位模式对于其他类型可能没有意义。这在程序中体现为给 data.f 赋值后访问 data.i,以及给 data.str 赋值后访问 data.f。

4.3 联合大小的计算

联合体的大小取决于其最大成员的大小,因为所有成员共用同一块内存空间。

union Un1 {
    char c[5]; // char 类型数组,占用 5 字节
    int i;     // int 类型,大小通常为 4 字节
};
union Un2 {
    short c[7]; // short 类型数组,每个 short 占用 2 字节,总共占用 14 字节
    int i;      // int 类型,大小通常为 4 字节
};
  • Un1 的大小将是其最大成员的大小,即 char 数组 c 的大小(5 字节)。不过,由于 int 类型可能需要按照特定的边界对齐(比如 4 字节对齐),联合体的实际大小可能需要向上取整到更大的对齐边界。具体的大小取决于编译器和平台,但如果 int 需要 4 字节对齐,Un1 的大小应该是 8 字节。
  • Un2 的大小将是其最大成员的大小,即 short 数组 c 的大小(14 字节)。和 Un1 一样,如果 int 需要 4 字节对齐,那么 Un2 的大小可能需要增加额外的填充,以满足对齐要求。然而,因为 14 已经是 2 的倍数(short 类型的自然对齐边界),Un2 不需要额外的填充就可以保证 int 成员对齐,所以 Un2 的大小应该是 14 字节。

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

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

相关文章

xhEditor实现WORD粘贴图片自动上传

1.下载示例&#xff1a; 从官网下载 http://www.ncmem.com/webapp/wordpaster/versions.aspx 从gitee中下载 https://gitee.com/xproer/wordpaster-php-xheditor1x 2.将插件目录复制到项目中 3.引入插件文件 定义插件图标 初始化插件&#xff0c;在工具栏中添加插件按钮 效果…

面向对象目录总结

【零】思维导图 【一】初识面向对象 Python 初识面向对象-CSDN博客 【二】面向对象-封装 Python 面向对象之封装和装饰器property_面向对象python封装property-CSDN博客 【三】面向对象-继承 Python 面向对象之继承和组合_面向对象 组合 继承-CSDN博客 【四】面向对象-多…

YOLOv9改进策略 | Conv篇 | 利用 Haar 小波的下采样HWD替换传统下采样(改变YOLO传统的Conv下采样)

一、本文介绍 本文给大家带来的改进机制是Haar 小波的下采样HWD替换传统下采样&#xff08;改变YOLO传统的Conv下采样&#xff09;在小波变换中&#xff0c;Haar小波作为一种基本的小波函数&#xff0c;用于将图像数据分解为多个层次的近似和细节信息&#xff0c;这是一种多分…

6.搭建Eureka

eureka-server自己也是一个微服务&#xff0c;所以eureka-server在启动的时候也会将自己注册到eureka上。eureka集群的时候&#xff0c;会将多个eureka相互注册&#xff0c;这个时候&#xff0c;defaultZone的值会有多个&#xff0c;用逗号隔开。 <?xml version"1.0&…

Mac读写U盘软件哪个好用 Mac读写U盘很慢怎么解决 macbookpro读取u盘

在使用Mac电脑时&#xff0c;读写U盘是一个常见的需求&#xff0c;特别是当U盘格式为NTFS时。选择适合的软件来实现这一操作至关重要。下面我们来看Mac读写U盘软件哪个好用&#xff0c;Mac读写U盘很慢怎么解决的相关内容。 一、Mac读写U盘软件哪个好用 在Mac上选择一款适合的…

程序设计语言—Python几种语言区别的总结

程序设计语言篇—Python&几种语言区别的总结 文章目录 程序设计语言篇—Python&几种语言区别的总结一、Python介绍&理解1.1 Python基础1.2 Python规范 二、标识符&变量&常量三、数据类型&运算符和表达式3.1 数据类型3.2 运算符&表达式 四、常用的函…

HarmonyOS ArkUI实战开发-NAPI数据类型

在前两篇文章里笔者简单介绍了 NAPI 工程结构以及生成的 cpp 源码部分&#xff0c;其中 JS 应用层传递过来的数据被封装在了 napi_value 中&#xff0c;使用前先要转换成对应的 C/C 数据类型&#xff0c;C/C 端的数据也要转换成 napi_value 数据类型传递给 JS 应用层&#xff0…

哈希表实现[很详细!]

目录 哈希表 定义节点类 根据hash码获取value 向hash表存入新key value,如果key重复,则更新value 根据hash码删除,返回删除的value 关于resize()一些问题的解答 冲突测试 MurmurHash 设计思考 练习 Leetcode01 Leetcode03 Leetcode49 Leetcode217 Leetcode136 L…

网络编程——TCP的特性之自动重传/流量控制/拥塞控制,一篇说清楚

文章目录 1. ARQ自动重传协议1.1 停止等待ARQ1.2 连续ARQ1.3 总结 2. TCP的流量控制3. TCP的拥塞控制3.1 慢开始算法3.2 拥塞避免算法3.3 快重传算法3.4 快恢复算法 1. ARQ自动重传协议 自动重传请求&#xff08;Automatic Repeat-reQuest&#xff09;&#xff0c;通过使用确认…

如何在Flask应用程序中使用JSON Web Tokens进行安全认证

密码、信用卡信息、个人识别号码&#xff08;PIN&#xff09;——这些都是用于授权和认证的关键资产。这意味着它们需要受到未经授权的用户的保护。 作为开发者&#xff0c;我们的任务是保护这些敏感信息&#xff0c;并且在我们的应用程序中实施强大的安全措施非常重要。 现在…

书生·浦语大模型实战营之 XTuner 微调 Llama 3 个人小助手认知

书生浦语大模型实战营之 XTuner 微调 Llama 3 个人小助手认知 Llama 3 近期重磅发布,发布了 8B 和 70B 参数量的模型,XTuner 团队对 Llama 3 微调进行了光速支持!!!开源同时社区中涌现了 Llama3-XTuner-CN 手把手教大家使用 XTuner 微调 Llama 3 模型。 XTuner:http://…

Pytorch 的数据处理 学习笔记

一. 数据集Dataset Dataset是一个抽象类&#xff0c;用于表示数据集。可以创建自定义的Dataset类来加载和准备好的数据&#xff0c;无论数据是存储在何处&#xff08;例如磁盘、内存或其他位置&#xff09;。PyTorch提供了一些内置的Dataset类&#xff0c;例如TensorDataset、…

【机器学习】特征筛选实例与代码详解

机器学习中的特征筛选 一、特征筛选的重要性与基本概念二、特征筛选的方法与实践1. 基于统计的特征筛选2. 基于模型的特征筛选3. 嵌入式特征筛选 三、总结与展望 在机器学习领域&#xff0c;特征筛选作为预处理步骤&#xff0c;对于提高模型性能、简化模型结构以及增强模型解释…

图像哈希:GLCM+DCT

文章信息 作者&#xff1a;Ziqing Huang期刊&#xff1a;IEEE&#xff08;一区&#xff09;题目&#xff1a;Perceptual Image Hashing with Texture and Invariant Vector Distance for Copy Detection 目的、实验步骤及结论 目的&#xff1a;使用GLCM进行全局特征的提取&am…

C# 开源SDK 工业相机库 调用海康相机 大恒相机

C# MG.CamCtrl 工业相机库 介绍一、使用案例二、使用介绍1、工厂模式创建实例2、枚举设备&#xff0c;初始化3、启动相机4、取图5、注销相机 三、接口1、相机操作2、启动方式3、取图4、设置/获取参数 介绍 c# 相机库&#xff0c;含海康、大恒品牌2D相机的常用功能。 底层采用回…

【Linux】在ubuntu快速搭建部署K8S(1.27)集群

ubuntu快速安装K8s1.27 &#xff08;一&#xff09;环境说明1.硬件环境2.Ubuntu环境设置 &#xff08;二&#xff09;安装配置containerd1.安装2.配置3.启动 &#xff08;三&#xff09;所有节点操作1.安装runc和cni2.节点系统设置、关闭临时分区3.修改内核参数4.安装 kubeadm、…

什么是 PCIe 及其工作原理?

什么是外围组件互连 Express (PCIe)&#xff1f; 外围组件互连 Express (PCIe) 是一种高速串行计算机扩展总线标准&#xff0c;可将设备连接到主板。 它于 2004 年首次推出&#xff0c;作为以前 PCI 和 AGP 方式的替代。 PCIe 允许处理器和各种扩展卡&#xff08;例如显卡、声…

PS入门|蒙版到底是个什么样的功能?看完就明白了

前言 前段时间一直说蒙版蒙版什么的&#xff0c;很多小伙伴估计都听得一头雾水。 抠个图要加蒙版&#xff0c;调个色要加蒙版。 小白感觉这个蒙版就像调味剂一样&#xff0c;啥都需要加一个蒙版。 动不动就加个蒙版&#xff0c;究竟是干啥用的&#xff1f; 今天咱们就深入来…

自动驾驶光学校准反射板

光学校准反射板是一种用于光学系统校准的重要工具。它以其高反射率和精确的几何特性&#xff0c;为光学仪器、光学系统和光学元件的校准提供了可靠的参考。在现代光学领域&#xff0c;光学校准反射板的应用已经深入到各个领域&#xff0c;从科学研究到工业生产&#xff0c;都离…

leetcode最大间距(桶排序+Python)

虽然直接排完序&#xff0c;再求最大差值更快&#xff0c;这里我们还是学一下桶排序。 桶排序主要维护一个bucket&#xff0c;初始bucket【i】 0&#xff0c;遍历nums&#xff0c;当i存在时&#xff0c;令bucket【i】 1&#xff0c;表示存在。遍历完nums&#xff0c;bucket中有…