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

C语言:构造类型

内容提要构造类型结构体共用体/联合体构造类型数据类型基本类型/基础类型/简单类型整型短整型short -- 2字节基本整型int -- 4字节长整型long -- 32位系统4字节/ 64位系统8字节长长整型long long 8字节大多数现代机器旧机器可能超过8字节C99新增注意以上类型又分为signed(默认) 和 unsigned浮点型单精度型float --4字节双精度型double --8字节长双精度型long double -- 16字节视平台而定C99新增字符型 char --1字节指针类型数据类型*32位系统4字节64位系统8字节void*通用指针类型万能指针32位系统4字节64位系统8字节空值类型void无返回值无形参不能修饰变量构造类型自定义类型结构体类型struct共用体/联合体类型union枚举类型enum结构体结构体定义【定义类型】定义自定义数据类型的一种关键字struct。语法struct 结构体名 // 结构体名自定义的数据类型名字 类似于int,double之类的 { 数据类型1 成员名称1; // 结构体中的变量叫做成员 数据类型2 成员名称2; ... };注意结构体中定义的变量称之为成员变量成员属性格式说明结构体名合法的标识符建议首字母大写所谓的结构体名就是自定义类型的类型名称数据类型nC语言支持的所有类型包括函数函数在这里用函数指针表示成员名称n合法的表示就是变量的命名标准数据类型n 成员名称n类似于定义变量定义了结构体中的成员注意结构体在定义的时候成员不能赋值示例struct Cat { int age 5; // 错误结构体定义的时候并未在内存中申请空间因此无法进行赋值 double height; // 正确 void (*run)(void);// 正确 };常见的定义格式方式1常规定义命名结构体只定义数据类型struct Student { int num; // 学号 char name[20]; // 姓名 char sex; // 性别 int age; // 年龄 char address[100]; // 籍贯 void (*info)(void);// 信息输出函数指针 };方式2匿名结构体常用于作为其他结构体的成员使用struct Dog // 命名结构体 { char *name; // 姓名 int age; // 年龄 struct // 匿名结构体 { // 定义结构体时不能省略成员否则编译报错 int year; // 年 int month;// 月 int day; // 日 } bithday; // 年龄匿名结构体一定要提供成员名称否则无法访问 };注意定义匿名结构体的同时必须定义结构体成员否则编译报错结构体可以作为另一个结构体的成员。总结结构体可以定义在局部位置函数作用域、块作用域也可以定义在全局位置推荐可以复用全局位置的结构体名和局部位置的结构体名可以相同遵循就近原则和变量的定义同理结构体类型的使用利用结构体类型定义变量、数组也可以作为函数的返回值和参数结构体类型的使用与基本数据类型的使用类似。结构体变量定义【定义变量】三种形式定义结构体变量说明结构体变量也被称作结构体对象或者结构体实例。第一种方式① 先定义结构体定义数据类型② 然后定义结构体变量定义变量示例// 定义结构体定义数据类型 struct A { int a; char b; }; ​ // 定义结构体实例/变量定义变量 struct A x; // A就是数据类型x就是变量名 struct A y; // A就是数据类型y就是变量名第二种方式① 在定义结构体的同时定义结构体变量同时定义数据类型和变量语法struct 结构体名 { 数据类型1 数据成员1; ... } 变量列表; 示例 struct A { int a; char b; } x, y; // A就是数据类型x,y就是变量名此时定义了一个结构体x和y就是这个结构体类型的变量。第三种方式① 在定义匿名结构体的同时定义结构体变量。示例struct { int a; char b; } x, y;此时定义了一个没有名字的结构体匿名结构体,xy是这个结构体类型的变量。匿名结构体优点少写一个结构体名称缺点只能使用一次定义结构体类型的同时必须定义变量。应用场景当结构体的类型只需要使用一次并且定义类型的同时定义了变量。作为其他结构体的成员使用。定义结构体同时变量初始化说明定义结构体的同时定义结构体变量并初始化struct Cat { int age; char color[20]; } cat;结构体成员部分初始化大括号不能省略结构体成员没有默认值是随机值和局部作用域的变量一致。案例/************************************************************************* File Name: demo01.c Author: 三道渊 Description: Created Time: 2025年05月27日 星期二 10时25分08秒 ************************************************************************/ ​ #include stdio.h ​ /** * 先定义结构体再定义结构体变量实例 */ void fun1() { // 定义结构体 struct A { int a; char b; }; ​ // 定义结构体变量 struct A x; struct A y; struct A x1,y1; } ​ /** * 定义结构体的同时定义结构体变量 */ void fun2() { struct A { int a; char b; } x,y; ​ struct A z; struct A x1,y1; } ​ /** * 定义匿名结构体的同时定义结构体变量 */ void fun3() { struct { int a; char b; } x,y; ​ struct { int a; char b; } z; } ​ int main(int argc,char *argv[]) { fun1(); fun2(); fun3(); ​ return 0; } ​结构体变量的使用【变量使用】结构体变量访问成员语法结构体变量名(实例名).成员名;① 可以通过访问成员进行赋值存数据② 可以通过访问成员进行取值取数据结构体变量未初始化结构体成员的值是随机的和局部作用域的变量和数组同理结构体变量定义时初始化成员建议用大括号{}标明数据的范围。结构体成员初始化可以部分初始化和数组类似部分初始化时一定要带大括号标明数据范围。未初始化的成员使用清零操作。案例/************************************************************************* File Name: demo01.c Author: 三道渊 Description: Created Time: 2025-08-01 10:47:18 ************************************************************************/ #include stdio.h ​ /** 定义全局的结构体方便被多个函数访问*/ struct Dog { char *name; // 名字 int age; // 年龄 char sex; // 性别 M:公W:母 void (*eat)(void); // 吃狗粮 }; ​ void eat() { printf(狗狗正在吃狗粮\n); } ​ /** * 方式1先定义再初始化 --- 结构体变量访问成员 */ void fun1() { // 定义结构体变量 struct Dog dog; // 结构体变量成员赋值 dog.name 旺财; dog.age 5; dog.sex M; dog.eat eat; // 结构体变量成员访问 printf(%s,%d,%c\n, dog.name, dog.age, dog.sex); // 访问成员方法函数 dog.eat(); } ​ /** * 方式2定义的同时初始化给变量成员初始化 */ void fun2() { // 定义结构体变量的同时给变量成员初始化 struct Dog d1 {旺财, 5, M, eat}; // 完整初始化按照顺序赋值 struct Dog d2 {.name 莱德, .sex M}; // C99之后支持部分成员初始化未初始化的成员自动填充0 struct Dog d3 {旺财}; // C99之后可以默认初始化第一个成员其他成员用0填充 // 结构体变量成员访问 printf(%s,%d,%c\n, d1.name, d1.age, d1.sex); printf(%s,%d,%c\n, d2.name, d2.age, d2.sex); printf(%s,%d,%c\n, d3.name, d3.age, d3.sex); } ​ int main(int argc, char *argv[]) { fun1(); printf(\n------------\n); fun2(); return 0; }结构体数组的定义【数组定义】什么时候需要结构体数组比如我们需要管理一个学生对象只需要定义一个struct Student yifanjiao;假如我们需要管理一个班的学生对象此时就需要定义一个结构体数组struct Student stus[50];定义存放结构体实例的数组称之为结构体数组。四种形式定义结构体数组第一种方式// 第一步定义一个结构体数组 struct Student { char *name; // 姓名 int age; // 年龄 float scores[3]; // 三门课程的成绩 } stus[3]; ​ // 第二步赋值 stus[0].name 张三; stus[0].age 21; stus[0].scores[0] 89; stus[0].scores[1] 99; stus[0].scores[2] 87; ​ stus[1].name 李四; stus[1].age 22; stus[1].scores[0] 66; stus[1].scores[1] 77; stus[1].scores[2] 88;第二种方式// 第一步定义一个学生结构体定义数据类型 struct Student { char *name; // 姓名 int age; // 年龄 float scores[3]; // 三门课程的成绩 }; ​ // 第二步定义结构体实例定义结构体实例 struct Student zhangsan {张三, 21, {89,99,87}}; struct Student lisi {李四, 22, {66,77,88}}; ​ // 第三步定义结构体数组 struct Student stus[] {zhangsan, lisi};第三种方式// 第一步定义一个学生结构体定义数据类型 struct Student { char *name; // 姓名 int age; // 年龄 float scores[3]; // 三门课程的成绩 }; ​ // 第二步定义结构体数组并初始化成员 struct Student stus[] { {张三, 21, {89,99,87}}, {李四, 22, {66,77,88}} };第四种方式// 第一步定义一个结构体数组并初始化 struct Student { char *name; // 姓名 int age; // 年龄 float scores[3]; // 三门课程的成绩 } stus[] { {张三, 21, {89,99,87}}, {李四, 22, {66,77,88}} };结构体数组的访问【数组访问】语法结构体成员.成员名 结构体指针 - 成员名 // - 结构体指针成员访问符举例// 方式1结构体成员访问 (*p).成员名 // 方式2结构体指针访问 p - 成员名案例/************************************************************************* File Name: demo02.c Author: 三道渊 Description: Created Time: 2025-08-01 11:29:40 ************************************************************************/ #include stdio.h ​ /* 定义全局的Student结构体 */ struct Student { int id; // 编号 char *name; // 姓名 int age; // 年龄 float scores[3]; // 三门课成绩 void (*info)(char*,int); // 信息输出 }; ​ void info(char* name, int age) { printf(大家好我是%s今年%d岁\n, name, age); } ​ int main(int argc, char *argv[]) { // 定义结构体实例并初始化 struct Student zhangsan {1, 张三, 21, {78,88,98}, info}; struct Student lisi {2, 李四, 22, {90,98,91}, info}; // lisi.info info // 定义结构体数组并初始化 struct Student stus[] {zhangsan, lisi}; // 计算数组的大小 int len sizeof(stus) / sizeof(stus[0]); // 用一个指针进行遍历 struct Student *p stus; // 表格-表头 printf(序号\t姓名\t年龄\t语文\t数学\t英语\n); for (; p stus len; p) { // 结构体成员访问不推荐 // printf(%d\t%s\t%d\t%.2f\t%.2f\t%.2f\t\n,(*p).id, (*p).name, (*p).age, (*p).scores[0], (*p).scores[1], (*p).scores[2]); // (*p).info((*p).name, (*p).age); // 结构体指针访问推荐 printf(%d\t%s\t%d\t%.2f\t%.2f\t%.2f\t\n,p-id, p-name, p-age, p-scores[0], p-scores[1], p-scores[2]); // 函数调用 p-info(p-name, p-age); } printf(\n); return 0; }结构体类型结构体数组案例需求对候选人得票的统计程序。设有3个候选人每次输入一个得票的候选人名字要求最后输出个人得票的结果。案例/************************************************************************* File Name: demo03.c Author: 三道渊 Description: Created Time: 2025-08-01 14:11:32 ************************************************************************/ #include stdio.h #include string.h ​ #define LEN 3 ​ /* 定义一个候选人结构体 */ struct Person { char name[20]; // 名字 int count; // 票数 }; ​ /** * 定义候选人数组并初始化 */ struct Person persons[LEN] { {卫宇星, 0}, {焦艺凡, 0}, {杨家辉, 0} }; ​ int main(int argc, char *argv[]) { // 定义循环变量 register int i, j; // 创建一个数组用来接收控制台录入的候选人名字 char leader_name[20]; // 使用一个for循环默认10个人参与投票 printf(世纪美男投票系统\n); for (i 0; i 10; i) { printf(请输入您觉得最帅的那位哥哥的名字\n); scanf(%s, leader_name); // 从候选人列表中匹配被投票的人 count for (j 0; j LEN; j) { // 判断两个字符串是否相等 strcmp if (strcmp(leader_name, persons[j].name) 0) { persons[j].count; // 票数1 } } } printf(\n); printf(\n投票结果\n); struct Person *p persons; // 指针p指向数组persons的第一个元素 // 遍历数组使用指针变量来遍历数组 for (; p persons LEN; p) { printf( %s:%d\n,p-name, p-count); } printf(\n); // 遍历数组使用指针来遍历数组 for (i 0; i LEN; i) { printf( %s:%d\n,(persons i)-name, (persons i)-count); } printf(\n); // 遍历数组使用下标来遍历数组 for (i 0; i LEN; i) { printf( %s:%d\n,persons[i].name, persons[i].count); } return 0; }结构体指针定义指向结构体变量或者结构体数组的起始地址的指针叫做结构体指针。语法struct 结构体名 *指针变量列表;举例/************************************************************************* File Name: demo04.c Author: 三道渊 Description: Created Time: 2025-08-01 14:44:34 ************************************************************************/ #include stdio.h ​ // 定义一个Dog结构体 struct Dog { char name[20]; int age; }; ​ int main(int argc, char *argv[]) { // 创建Dog实例 struct Dog dog {苟富贵, 5}; // 基于结构体变量的结构体指针 struct Dog *p dog; printf(%s,%d\n, p-name, p-age); // 创建Dog数组 struct Dog dogs[] { {苟富贵, 5}, {勿相忘, 6} }; // 基于结构体数组元素的结构体指针 struct Dog *p1 dogs; int len sizeof(dogs)/sizeof(dogs[0]); for (; p1 dogs len ; p1) { printf(%s,%d\n, p1-name, p1-age); } return 0; }结构体成员的访问结构体成员访问结构体数组名访问结构体成员语法结构体数组名 - 成员名; (*结构体数组名).成员名; // 等价于上面写法举例printf(%s:%d\n,persons-name, persons-count);结构体成员访问符.左侧是结构体变量也可以叫做结构体对象访问成员符右侧是结构体成员。-左侧是结构体指针也可以叫做结构体指针访问成员符右侧是结构体成员。举例struct Person *p persons; // p就是结构体指针 for(; p persons len; p) printf(%s:%d\n,p-name,p-count);访问结构体成员有两种类型三种方式类型1通过结构体变量对象|示例访问成员struct Stu { int id; char name[20]; } stu; // 结构体变量 // 访问成员 stu.name;类型2通过结构体指针访问成员第1种指针引用访问成员struct Stu { int id; char name[20]; } stu; struct Stu *p stu; // 指针引用访问成员 p - name; // 等价于 (*p).name;第2种指针解引用间接访问成员struct Stu { int id; char name[20]; } stu; struct Stu *p stu; // 指针引用访问成员 (*p).name; // 等价于 p - name;结构体数组中元素的访问// 结构体数组 struct Stu { int id; // 编号成员 char name[20]; // 名字成员 float scores[3];// 三门成绩成员 } stus[3] { {1,张三{90,89,78}, {2,李四{90,88,78}, {3,王五{77,89,78}, }; // 取数据 --- 下标法 printf(%s,%.2f\n, stus[1].name, stus[1].scores[1]);// 李四 88 // 取数据 --- 指针法 printf(%s,%.2f\n, stus-name, stus-scores[2]);// 张三 78 printf(%s,%.2f\n, (stus1) - name, (stus1) - scores[1]);// 李四 88 printf(%s,%.2f\n, (*(stus1)).name, (*(stus1)).scores[1]);// 李四 88小贴士结构体是自定义数据类型它是数据类型用法类似于基本类型的int结构体数组它是存放结构体对象的数组类似于int数组存放int数据基本类型数组怎么用结构体数组就怎么用---可以遍历可以作为形式参数也可以做指针等结构体类型的使用案例结构体可以作为函数的返回类型形式参数等。举例/************************************************************************* File Name: demo05.c Author: 三道渊 Description: Created Time: 2025-08-01 14:55:44 ************************************************************************/ #include stdio.h #include string.h ​ /** * 定义一个Cat结构体 */ struct Cat { char *name; // 姓名 int age; // 年龄 char color[20]; // 颜色 }; ​ /** * 结构体类型作为形式参数 */ void test1(struct Cat c) { printf(test1\n%s,%d,%s\n, c.name, c.age, c.color); } ​ /** * 结构体类型作为函数返回类型 */ struct Cat test2(struct Cat c) { c.name 金宝; c.age 3; strcpy(c.color, 黄色); return c; } ​ /** * 结构体指针作为参数和返回类型 * 需求根据Cat的name在Cat数组中匹配Cat对象 */ struct Cat *test3(struct Cat *cats, int len, char* name) { struct Cat *p cats; for (; p cats len; p) { if (strcmp(name, p-name) 0) return p; // p是指针 } return NULL; } ​ int main(int argc, char *argv[]) { struct Cat cat {招财, 5, 白色}; test1(cat); struct Cat c test2(cat); printf(test2\n%s,%d,%s\n, c.name, c.age, c.color); struct Cat cats[] { {招财, 5, 白色}, {金宝, 3, 金色} }; struct Cat *c2 test3(cats,sizeof(cats)/sizeof(cats[0]),招财); printf(test3\n%s,%d,%s\n, c2-name, c2-age, c2-color); return 0; }结构体类型求大小字节对齐字节对齐的原因硬件要求某些硬件平台如ARM、x86要求特定类型的数据必须对齐到特定地址否则会引发性能下降或硬件异常。优化性能对齐的数据访问速度更快。例如CPU访问对齐的int数据只需一次内存操作而未对齐的数据可能需要多次操作。字节对齐规则默认对齐规则结构体的每个成员按其类型大小和编译器默认对齐数通常是类型的自然对齐数对齐。结构体的总大小必须是最大对齐数的整数倍。对齐细节基本类型的对齐数char1字节、short2字节、int4字节、double8字节。结构体成员的对齐每个成员的起始地址必须是对齐数的整数倍。结构体总大小的对齐结构体的总大小必须是其最大对齐数的整数倍。#pragma pack(n)的影响使用#pragma pack(n)可以强制指定对齐数为nn为 1、2、4、8、16。此时每个成员的对齐数取n和其类型大小的较小值。结构体的总大小必须是n和最大对齐数中的较小值的整数倍。对齐示例默认对齐struct S1 { char c; // 1字节偏移0 int i; // 4字节需对齐到4填充3字节偏移4-7 double d;// 8字节需对齐到8偏移8~15 } struct S2 { double d; char c; int i; } struct S3 { char c; double d; int i; }内存分析总结结构体中成员的顺序会影响到结构体最终的大小。使用#pragma pack(1)自定义对齐规则(1)对齐的字节数#pragma pack(1) // 对齐数之前的字节数能被1整数 struct S1 { char c; // 1字节 (偏移0) 1 int i;// 4字节 偏移1~44 double d;// 8字节 偏移5~128 }; #pragma pack() // S1 的大小为 13字节 #pragma pack(2) // 对齐数之前的字节数能被2整数 struct S1 { char c; // 1字节 (偏移0填充1字节) 2 int i;// 4字节 偏移2~54 double d;// 8字节 偏移6~138 }; #pragma pack() // S1 的大小为 14字节 char -1 1 int #pragma pack(4) // 对齐数之前的字节数能被4整数 struct S1 { char c; // 1字节 (偏移0填充3字节) 4 int i;// 4字节 偏移4~74 double d;// 8字节 偏移8~158 }; #pragma pack() // S1 的大小为 16字节在GNU标准中可以在定义结构体时指定对齐规则__attribute__((packed)); -- 结构体所占内存大小是所有成员所占内存大小之和 ——attribute__((aligned(n))); -- 设置结构体占n个字节如果n比默认值小n不起作用n必须是2的次方案例/************************************************************************* File Name: demo06.c Author: 三道渊 Description: Created Time: 2025-08-01 16:08:50 ************************************************************************/ #include stdio.h ​ int main(int argc, char *argv[]) { struct Cat{ char sex __attribute((aligned(2))); // 设置 char按照2字节对齐 int id; // 4 char name[20];// 20 }__attribute__((packed)); // 28 25 printf(%ld\n,sizeof(struct Cat));// 28 25 return 0; }柔性数组定义柔性数组不占有结构体的大小。特点柔性数组必须是结构体的最后一个成员结构体大小在编译时是未确定的必须动态分配内存指定数组的大小语法struct St { ... char arr[]; }案例/************************************************************************* File Name: demo07.c Author: 三道渊 Description: Created Time: 2025-08-01 16:21:01 ************************************************************************/ #include stdio.h #include stdlib.h #include string.h ​ /* 定义包含柔性数组的结构体 */ struct FAStruct { int len; // 用于记录柔性数组的长度 char data[]; // 柔性数组注意这里没有指定大小。柔性数组只能用于结构体并且只能是最后一个成员。 }; ​ int main(int argc, char *argv[]) { const char* str1 Hello, Flexible Array!; const char* str2 hello world!; int str_len1 strlen(str1) 1; // 1 为了存储\0 int str_len2 strlen(str2) 1; // 使用calloc分配内存为结构头和柔性数组部分分配内存 struct FAStruct *fas1 (struct FAStruct*)calloc(1,sizeof(struct FAStruct) str_len1); // 结构体空间大小 数组空间大小 struct FAStruct *fas2 (struct FAStruct*)calloc(1,sizeof(struct FAStruct) str_len2); // 结构体空间大小 数组空间大小 if (!fas1 || !fas2) { perror(内存申请失败); return -1; } fas1-len str_len1 - 1; // 不包含字符串结束符的长度 strcpy(fas1-data, str1); fas2-len str_len2 - 1; // 不包含字符串结束符的长度 strcpy(fas2-data, str2); printf(字符串1%s,%d\n, fas1-data,fas1-len); printf(字符串2%s,%d\n, fas2-data,fas2-len); // 释放内存 free(fas1); free(fas2); return 0; }结构体的常见陷阱与最佳实践常见陷阱成员访问越界访问不存在的结构体成员。struct Point p; p.z 10; // 错误Point结构体没有z成员内存泄漏忘记释放动态分配的结构体内存。struct Point *p malloc(sizeof(struct Point)); p-x 10; // 没有free(p)导致内存泄漏悬挂指针/空悬指针使用已经释放的内存或未初始化的指针。struct Point *p malloc(sizeof(struct Point)); free(p); // 释放了p指向的内存 p-x 10; // 错误p现在是悬挂指针结构体大小计算错误忘记考虑编译器的内存对齐。struct { char a; int b; } s; // sizeof(s)可能是8而不是5最佳实践使用typedef简化语法为结构体创建简短的别名。typedef struct { int x; int y; } Point;将相关数据组织在一起使用结构体封装相关数据。struct Student { char name[50]; int age; float grade; };避免过大的结构体将大型数据结构分解为多个较小的结构体。合理使用指针对于大型结构体使用指针而不是值传递。注意内存管理确保正确分配和释放动态内存。共用体/联合体类型定义使几个不同变量占用同一段内存的结构。共用体按定义中需要存储空间最大的成员来分配存储单元其他成员也是使用该空间它们的首地址是相同。定义格式union 共用体名称 { 数据类型 成员名; 数据类型 成员名; ... };共用体的定义和结构体类似。可以有名字也可以匿名共用体在定义时也可以定义共用体变量共用体在定义时也可以初始化成员共用体也可以作为形参和返回值类型使用共用体也可以定义共用体变量...也就是说结构体的语法共用体都支持注意共用体弊大于利尽量少用一般很少用共用体变量在某一时刻只能存储一个数据并且也只能取出一个数共用体所有成员共享同一内存空间同一时间只能存储一个值可能导致数据覆盖共用体和结构体都是自定义数据类型用法类似于基本数据类型共用体可以是共用体的成员也可以是结构体的成员结构体可以是结构体的成员也可以是共用体的成员案例/************************************************************************* File Name: demo06.c Author: 三道渊 Description: Created Time: 2025年05月27日 星期二 17时22分08秒 ************************************************************************/ ​ #include stdio.h ​ /** * 定义共用体 */ union S { char a; float b; int c; };// S的大小是4字节 ​ // 共用体作为共用体成员 union F { char a; union S s; // 4字节 };// F的大小是4字节 ​ // 定义一个结构体 struct H { int a; char b; };// H的大小是8字节 ​ // 结构体作为结构体成员 struct I { int a; int b; struct H h; }; // I的大小是16字节 ​ ​ // 共用体作为结构体成员 struct J { int a; // 4 char b; // 1 3 union S s; // 4 }; // J的大小是12字节 ​ void test1() { // 定义一个共用体(数据类型) union Obj { int num; char sex; double score; }; ​ // 定义匿名共用体 union { int a; char c; } c; ​ // 定义变量 union Obj obj; // 存储数据 obj.num 10; // 共用体空间数据10 obj.sex A;// 共用体空间数据A 65 覆盖数据 ​ // 运算 obj.num 5; // 共用体空间数据70 覆盖数据 F sizeof(数据类型|变量名) ​ printf(%lu,%lu,%d,%c,%.2lf\n,sizeof(obj),sizeof(union Obj), obj.num, obj.sex, obj.score); } ​ int main(int argc,char *argv[]) { test1(); return 0; }要求共用体在使用的时候建议存取时使用的成员是一致的。也就是使用成员a存数据必须使用成员b取数据。结构体与共用体的主要区别内存占用结构体的成员是连续存储的每个成员都有自己的内存空间。共用体的所有成员共享同一块内存空间共享所有成员中最大成员的空间。访问方式结构体的成员可以同时访问。共用体的成员不能同时访问因为它们共享同一块内存空间。使用场景结构体适用于需要同时存储多个不同类型数据的情况。共用体适用于需要在同一时间存储不同类型数据中的一种的情况可以节省内存。

相关文章:

C语言:构造类型

内容提要构造类型结构体共用体/联合体构造类型数据类型基本类型/基础类型/简单类型整型短整型:short -- 2字节基本整型:int -- 4字节长整型:long -- 32位系统4字节/ 64位系统8字节长长整型:long long 8字节(大多数现代…...

001、性能优化基础:慢SQL诊断与执行计划分析

昨天凌晨又被告警短信吵醒了,线上某核心接口的P99响应时间飙到了3秒。登录服务器一看,MySQL的CPU已经跑满,processlist里堆了二十几个相同的查询——又是慢SQL惹的祸。这种场景咱们做后端开发的太熟悉了,今天就来聊聊怎么系统性地…...

C++高性能网络库ZLToolKit资源池源码解析:如何用智能指针实现对象复用与自动回收

C高性能网络库ZLToolKit资源池源码解析:智能指针实现对象复用与自动回收 在C高性能服务器开发中,频繁的对象创建与销毁往往是性能瓶颈之一。想象一下这样的场景:一个直播服务器每秒需要处理数万条消息,每条消息都需要临时创建对象…...

JVM 内存管理 2026:深度解析与调优实战

JVM 内存管理 2026:深度解析与调优实战我是 Alex,一个在 CSDN 写 Java 架构思考的暖男。看到新手博主写技术踩坑记录总会留言:"这个 debug 思路很 solid,下次试试加个 circuit breaker 会更优雅。"我的文章里从不说空话…...

Steam API集成:构建智能游戏生态的完整PHP解决方案

Steam API集成:构建智能游戏生态的完整PHP解决方案 【免费下载链接】Steam A composer package to make use of the steam web api. 项目地址: https://gitcode.com/gh_mirrors/stea/Steam 在当今游戏开发和社区管理领域,与Steam平台的深度集成已…...

MIL图像库实战:从采集卡配置到Qt应用开发

1. 工业视觉项目开发全流程解析 第一次接触MIL图像库时,我被它强大的硬件抽象能力震撼到了。这个由Matrox开发的图像处理库,就像一位经验丰富的翻译官,把不同品牌采集卡的硬件差异统统屏蔽掉。想象一下,你手里有Basler、AVT、Dals…...

DriverStore Explorer:Windows驱动全生命周期管理的开源解决方案——解决驱动冗余与设备冲突的高效工具

DriverStore Explorer:Windows驱动全生命周期管理的开源解决方案——解决驱动冗余与设备冲突的高效工具 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer Windows系统中驱动程…...

如何解决bilibili-api中BV号与AV号转换的技术难题?

如何解决bilibili-api中BV号与AV号转换的技术难题? 【免费下载链接】bilibili-api 哔哩哔哩常用API调用。支持视频、番剧、用户、频道、音频等功能。原仓库地址:https://github.com/MoyuScript/bilibili-api 项目地址: https://gitcode.com/gh_mirrors…...

Windows 11 + RTX4060Ti 实战:用PyTorch复现Kaggle冠军的U-Net,搞定Kvasir息肉分割

Windows 11 RTX4060Ti 实战:用PyTorch复现Kaggle冠军的U-Net,搞定Kvasir息肉分割 在消费级硬件上实现专业级医学图像分割并非遥不可及。当RTX 40系列显卡遇上PyTorch框架,配合Kaggle冠军团队的U-Net架构,我们完全可以在Windows 1…...

中文大模型实战测评:MiniMax、GLM、Kimi谁更适合你的需求?(附详细对比表)

中文大模型实战测评:MiniMax、GLM、Kimi谁更适合你的需求? 当企业技术团队或个人开发者面临中文大模型选型时,往往陷入"参数崇拜"与"场景适配"的矛盾中。本文基于三个月真实项目测试数据,从工程落地视角拆解三…...

保姆级教程:在Ubuntu 20.04上搞定Ollama WebUI可视化界面(含Node.js 18.19.0安装避坑)

零基础在Ubuntu 20.04上部署Ollama WebUI全攻略 第一次在Linux服务器上部署Web应用?别担心,这篇教程会像老朋友一样手把手带你完成整个流程。我们将从最基础的环境检查开始,一步步安装Node.js、配置ollama-webui,直到最终在浏览器…...

OFA图像描述效果展示:COCO风格caption生成——简洁、准确、自然

OFA图像描述效果展示:COCO风格caption生成——简洁、准确、自然 1. 项目概述 今天要给大家展示一个特别实用的AI工具——基于OFA模型的图像描述生成系统。这个工具能够自动为任何图片生成简洁、准确、自然的英文描述,就像给图片配上了专业的文字说明。…...

苹果为 iOS 18 发布安全补丁,应对 DarkSword 漏洞威胁

苹果为 iOS 18 发布安全补丁,抵御 DarkSword 攻击苹果为仍运行 iOS 18 的 iPhone 发布了安全补丁,旨在保护这些设备免受危险的 DarkSword 漏洞攻击。据谷歌以及安全公司 iVerify 和 Lookout 报告,DarkSword 是一种极其恶劣的间谍软件漏洞&…...

当DWA遇上模糊控制:让路径规划更“聪明

基于改进动态窗口 DWA 模糊自适应调整权重的路径基于改进动态窗口 DWA 模糊自适应调整权重的路径规划算法 MATLAB 源码文档 《栅格地图可修改》 基本DWA算法能够有效地避免碰撞并尽可能接近目标点,但评价函数的权重因子需要根据实际情况进行调整。 为了提高DWA算法的…...

长脉冲激光打孔技术及其与水平集算法的融合应用

长脉冲激光打孔,水平集算法工业级激光打孔就像用光做的"绣花针",在金属表面精准戳出微米级孔洞。但当我们把激光脉冲时间拉长到毫秒量级时,事情就变得有趣起来——材料不再是瞬间汽化,而是经历缓慢的熔融、流动、再凝固…...

告别本地卡顿:用PyCharm专业版SSH连接远程服务器,把算力搬到云端(附环境配置避坑点)

告别本地卡顿:用PyCharm专业版SSH连接远程服务器,把算力搬到云端(附环境配置避坑点) 当你的笔记本风扇开始像喷气发动机一样轰鸣,而TensorFlow模型训练进度条却像蜗牛爬行时,是时候考虑把开发环境搬到云端了…...

卫生经济学中模型搭建与分析的奇妙之旅

马尔可夫模型,马科夫模型,Markov Model搭建,决策树模型 卫生经济学,药物经济学评价,成本效果分析,成本效益分析,成本效用分析,CEA,health economics,pharmaco…...

TargetMol明星分子—— 2‘,3‘-cGAMP

2,3-cGAMP 是哺乳动物细胞中的内源性 cGAMP。cGAMP 分子属于环状二核苷酸(CDNs)家族,以三种不同的形式存在:3′3′-cGAMP、2′3′-cGAMP和 3′2′-cGAMP。由哺乳动物细胞中环鸟苷腺苷酸合成酶(cyclic guanosine monoph…...

DLSS Swapper实战指南:高效管理DLSS版本3步达成游戏性能跃升

DLSS Swapper实战指南:高效管理DLSS版本3步达成游戏性能跃升 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 当你在4K分辨率下启动《赛博朋克2077》,满心期待沉浸在夜之城的霓虹中时&#xff0c…...

告别电量焦虑:用Python+卡尔曼滤波手把手教你DIY一个高精度电池SOC估算器

告别电量焦虑:用Python卡尔曼滤波手把手教你DIY一个高精度电池SOC估算器 每次看到手机电量从20%突然跳到5%,或是电动工具在关键时刻罢工,你是否好奇工程师如何准确预测电池剩余容量?今天我们将用Python和卡尔曼滤波算法&#xff0…...

3款自动化工具提升文档下载效率:智能识别与批量处理完整指南

3款自动化工具提升文档下载效率:智能识别与批量处理完整指南 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是…...

JS 入门通关手册(35):执行上下文、调用栈与作用域链深度解析

一、什么是执行上下文?执行上下文(Execution Context)是 JS 代码运行时的环境,JS 引擎会为每一段可执行代码创建一个上下文,用来管理变量、作用域、this 指向等。简单理解:一段代码在哪里跑、能访问什么、t…...

【Proteus 仿真实战】基于51单片机的智能测距与自适应报警系统设计

1. 项目背景与核心功能 最近在做一个基于51单片机的智能测距系统仿真项目,发现很多初学者对如何实现自适应报警功能特别感兴趣。这个项目最吸引人的地方在于它不仅仅是个简单的距离测量装置,而是能根据危险程度自动调整报警策略的智能系统。想象一下&…...

终极视频修复指南:如何使用Untrunc轻松恢复损坏的MP4/MOV文件

终极视频修复指南:如何使用Untrunc轻松恢复损坏的MP4/MOV文件 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 你是否曾经遇到过珍贵的视频文件突然无法播…...

Midscene.js:重塑UI自动化的革命性AI视觉驱动方案

Midscene.js:重塑UI自动化的革命性AI视觉驱动方案 【免费下载链接】midscene AI-powered, vision-driven UI automation for every platform. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 你是否曾为编写复杂的UI自动化脚本而头疼&#xff…...

ViGEmBus驱动全攻略:解锁游戏控制新可能

ViGEmBus驱动全攻略:解锁游戏控制新可能 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 1. 驱动异常诊断:从现象到本质的定位方法 当…...

5步搞定Jimeng LoRA测试台:Streamlit界面,LoRA版本智能排序

5步搞定Jimeng LoRA测试台:Streamlit界面,LoRA版本智能排序 1. 项目概述:轻量级LoRA测试系统 Jimeng LoRA测试台是一款专为模型开发者设计的轻量化文本生成图像系统。它基于Z-Image-Turbo文生图底座,实现了动态多版本LoRA热切换…...

课灵h5p-标签页 (Tabs)教程

标签页 (Tabs)教程 标签页 (Tabs) 是一种高效的内容容器,通过水平切换的选项卡界面来组织信息。它允许你在同一页面空间内并行展示多个同层级的主题(如不同类别的资源、不同语言的版本),帮助学习者按需浏览,保持界面整…...

炸锅!Claude Code 完整源码意外泄露,51 万行核心代码直接开源!

突发!Claude Code 意外开源 51 万行源码全网曝光 2026 年 3 月 31 日,AI 圈迎来重磅事件 ——Anthropic 旗下 Claude Code 因 npm 配置失误,通过 source map 文件意外泄露全部源码,超 1900 个文件、51.2 万行 TypeScript 代码公开…...

Obsidian插件翻译终极指南:5分钟让所有插件说你的母语

Obsidian插件翻译终极指南:5分钟让所有插件说你的母语 【免费下载链接】obsidian-i18n 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-i18n 你是否曾经因为喜欢的Obsidian插件只有英文界面而感到困扰?或者因为语言障碍而无法充分发挥插…...