尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Linux嵌入式学习——结构体/共用体/枚举/位运算,预编译及底层结构
前言本篇学习结构体/共用体/枚举类型和位运算的相关知识。预编译命令及底层内存结构。一、结构体专门用来构造复杂的数据类型解决不同数据类型批量处理问题。1.1 定义struct 结构体名 {成员列表} //注意结束必须加分号1未初始化的部分默认为02结构体名变量命名规则3成员列表不同的数据类型的定义。4同类型结构体变量可以直接相互赋值1.2 成员访问普通变量用 . 点指针变量用 - 传参优化结构体做形参或返回值时建议用指针避免值拷贝带来的空间和时间浪费1.3 内存对齐/结构体大小/存储方式成员对齐/自然边界对齐每个成员相对于结构体首地址的偏移量必须是该成员大小或其对齐数的整数倍比如一个整型int数据大小为4字节占4个地址它的首地址必须是4的整数倍整体对齐/以最大成员来对齐结构体总大小必须是最大成员大小的整数倍举例比如字符型数组char s[10],int a。 这里先放字符型十个然后放整型整型必须是4的倍数。然后总大小就是离104 14最近的4的倍数的大小即16字节比如两个数据char和int结构体的总大小是最大成员的整数倍就是本来是14 5个字节但是必须浪费3个字节到8字节。8是4的整数倍1.4 示例结构体定义、变量、数组、指针访问#include stdio.h struct stu { char name[20]; int sno; int age; float score; }; int main(void) { struct stu s {tom, 110, 18, 99.5}; // 定义并初始化 struct stu arr[3] { {a, 1, 18, 80}, {b, 2, 19, 90}, {c, 3, 20, 85} }; struct stu *p s; printf(%s %d %d %.2f\n, s.name, s.sno, s.age, s.score); printf(%s %d %d %.2f\n, p-name, p-sno, p-age, p-score); for (int i 0; i 3; i) printf(%s %d %d %.2f\n, (arr i)-name, (arr i)-sno, (arr i)-age, (arr i)-score); return 0; }结构体大小与内存对齐验证#include stdio.h struct a { char a; // 1 3 填充 int b; // 4 char c; // 1 3 填充 }; // 总大小 12 struct b { char a; char c; int b; }; // 总大小 8 int main(void) { printf(sizeof(struct a) %zu\n, sizeof(struct a)); // 12 printf(sizeof(struct b) %zu\n, sizeof(struct b)); // 8 return 0; }结构体数组输入输出#include stdio.h #include stdlib.h struct stu { char name[20]; char sex[10]; int age; float score; }; void InputData(struct stu *p, int n) { for (int i 0; i n; i) { scanf(%19s, (p i)-name); scanf(%9s, (p i)-sex); scanf(%d, (p i)-age); scanf(%f, (p i)-score); } } void Output(struct stu *p, int n) { printf(\tname\tsex\tage\tscore\n); for (int i 0; i n; i) { printf(\t%s\t%s\t%d\t%.2f\n, (p i)-name, (p i)-sex, (p i)-age, (p i)-score); } } int main(void) { int n 0; printf(输入学生人数:\n); if (scanf(%d, n) ! 1 || n 0) return -1; struct stu *demo (struct stu *)malloc(n * sizeof(struct stu)); if (demo NULL) return -1; printf(输入学生数据-name sex age score:\n); InputData(demo, n); Output(demo, n); free(demo); demo NULL; return 0; }结构体 qsort 回调#include stdio.h #include stdlib.h #include string.h struct tea { char name[20]; int sno; int age; float score; }; int cmpScore(const void *a, const void *b) { const struct tea *p (const struct tea *)a; const struct tea *q (const struct tea *)b; if (p-score q-score) return -1; // 降序 if (p-score q-score) return 1; return 0; } int cmpSno(const void *a, const void *b) { const struct tea *p (const struct tea *)a; const struct tea *q (const struct tea *)b; return p-sno - q-sno; } int cmpName(const void *a, const void *b) { const struct tea *p (const struct tea *)a; const struct tea *q (const struct tea *)b; return strcmp(p-name, q-name); } void Output(struct tea *s, int len) { for (int i 0; i len; i) printf(%s %d %d %.2f\n, s[i].name, s[i].sno, s[i].age, s[i].score); } int main(void) { struct tea s[3] { {c, 1, 34, 88}, {b, 2, 35, 87}, {a, 3, 23, 89} }; int len (int)(sizeof(s) / sizeof(s[0])); qsort(s, len, sizeof(struct tea), cmpScore); printf(--- by score ---\n); Output(s, len); qsort(s, len, sizeof(struct tea), cmpName); printf(--- by name ---\n); Output(s, len); qsort(s, len, sizeof(struct tea), cmpSno); printf(--- by sno ---\n); Output(s, len); return 0; }最大值struct tea *maxScore(struct tea *s, int len) { struct tea *max s; for (int i 1; i len; i) if ((s i)-score max-score) max s i; return max; }typedef 结构体与指针别名#include stdio.h typedef struct { char name[20]; int sno; } stu_t; typedef stu_t *stu_p; int main(void) { stu_t s {wang hai, 112}; stu_p p s; printf(%s--%d\n, p-name, p-sno); return 0; }二、共用体使几个不同类型的变量共享同一块内存早期省空间2.1 定义union 共用体名 { 成员列表 }1初始化只能给首个成员赋值连续赋值时后赋的值会覆盖前面的值2连续赋值时共用体最终结果取决于内存中最终存储了什么。3后赋值的一定会修改原有内容。所有成员变量的起始地址是一样的2.2 大小占用内存最大成员的空间大小2.3 应用1IP地址的存储2判断大小端2.4 示例共用体基础#include stdio.h union demo { unsigned int a; unsigned short c; unsigned char d; }; int main(void) { union demo f; f.a 0x12345678; printf(a %#x\n, f.a); // 0x12345678 printf(c %#x\n, f.c); // 低 16 位 0x5678小端 printf(d %#x\n, f.d); // 最低字节 0x78小端 printf(sizeof(union demo) %zu\n, sizeof(union demo)); // 4 return 0; }用 memcpy 查看 float 的位模式#include stdio.h #include string.h union demo { float b; unsigned int bits; }; int main(void) { union demo f; f.b 1.0f; unsigned int bits; memcpy(bits, f.b, sizeof(bits)); printf(1.0f bits %#x\n, bits); // 0x3f800000 return 0; }共用体检测大小端函数封装#include stdio.h int isLittleEndian(void) { union { unsigned int i; unsigned char c[4]; } u {0x01020304}; return u.c[0] 0x04; // 小端低地址存低字节 } int main(void) { if (isLittleEndian()) printf(Little Endian\n); else printf(Big Endian\n); return 0; }共用体嵌套结构体学生/教师共用 data#include stdio.h struct member { char name[20]; int no; union { float salary; // 教师 float score; // 学生 } d; }; int main(void) { struct member stu {tom, 1, .d.score 99.5f}; struct member tea {jack, 2, .d.salary 8000.0f}; printf(%s %.2f\n, stu.name, stu.d.score); printf(%s %.2f\n, tea.name, tea.d.salary); return 0; }共用体做 IP 地址点分十进制与整数转换#include stdio.h union ip { unsigned int addr; unsigned char byte[4]; }; int main(void) { union ip u; u.addr 0xC0A8015D; // 192.168.1.93 printf(%u.%u.%u.%u\n, u.byte[0], u.byte[1], u.byte[2], u.byte[3]); return 0; }三、枚举用有意义的符号代表常量如状态机红绿灯提高可读性3.1 定义enum 枚举名 { 标识符1, 标识符2, ... 标识符N };本质是整型默认从0开始依次递增1如果没有显式赋值第一个枚举成员的默认值为0后续成员依次1。可以在声明时手动指定值后面的成员如果没有指定会基于前面成员的值继续1。3.2 好处1提高可读性2便于维护和修改3增加代码的自解读性3.3 枚举与宏枚举带有类型检查编译阶段且能将相关的常量聚合在一起 宏只是预处理阶段的文本替换#include stdio.h #define M_RED 1 enum { E_RED 1 }; int main(void) { printf(%d %d\n, M_RED, E_RED); // 宏是预处理文本替换不做类型检查 // 枚举是数据类型编译期检查相关常量可放在一起。 return 0; }3.4 示例枚举基础用法#include stdio.h enum light { RED 1, GREEN, YELLOW }; int main(void) { int i 0; printf(Input a num(1,2,3):); if (scanf(%d, i) ! 1) return -1; switch (i) { case RED: printf(RED\n); break; case GREEN: printf(GREEN\n); break; case YELLOW: printf(YELLOW\n); break; default: printf(error input!\n); break; } return 0; }枚举表示星期#include stdio.h enum Week { Mon 1, Tue, Wed, Thu, Fri, Sat, Sun }; int main(void) { int day 0; scanf(%d, day); switch (day) { case Mon: printf(Monday\n); break; case Tue: printf(Tuesday\n); break; case Wed: printf(Wednesday\n); break; case Thu: printf(Thursday\n); break; case Fri: printf(Friday\n); break; case Sat: printf(Saturday\n); break; case Sun: printf(Sunday\n); break; default: printf(error input!\n); break; } return 0; }typedef enum 作函数参数#include stdio.h typedef enum { OP_INPUT 1, OP_OUTPUT, OP_TOPONE, OP_EXIT } OpCode; void doOp(OpCode op) { switch (op) { case OP_INPUT: printf(input\n); break; case OP_OUTPUT: printf(output\n); break; case OP_TOPONE: printf(topone\n); break; case OP_EXIT: printf(exit\n); break; default: printf(error\n); break; } } int main(void) { doOp(OP_INPUT); doOp(OP_EXIT); return 0; }四、位运算4.1 位运算相关用法4.2 示例统计 int 中 1 二进制的个数#include stdio.h int countOne(unsigned int n) { int cnt 0; for (int i 0; i 32; i) if ((1u i) n) cnt; return cnt; } int main(void) { unsigned int a 131451; printf(%d\n, countOne(a)); return 0; }统计 1 的个数优化n (n-1)int countOneFast(unsigned int n) { int cnt 0; while (n) { n n - 1; // 每次消掉最低位的 1 cnt; } return cnt; }置位、清位、翻转位、判断位#include stdio.h void setBit(unsigned int *x, int i) { *x | (1u i); } void clearBit(unsigned int *x, int i) { *x ~(1u i); } void toggleBit(unsigned int *x, int i) { *x ^ (1u i); } int getBit(unsigned int x, int i) { return (x i) 1u; } int main(void) { unsigned int reg 0xFF; clearBit(reg, 4); printf(%#x\n, reg); // 0xef reg 0xFF; reg ~(1u 4 | 1u 6); printf(%#x\n, reg); // 0xaf reg 0; setBit(reg, 0); setBit(reg, 2); printf(%#x\n, reg); // 0x5 toggleBit(reg, 2); printf(%#x\n, reg); // 0x1 printf(%d\n, getBit(reg, 0)); // 1 return 0; }偶数位清 0、奇数位置 1#include stdio.h int main(void) { unsigned int a 0xFFFFFFFF; for (int i 0; i 16; i) a ~(1u (2 * i)); // 偶数位清 0 printf(%#x\n, a); // 0xaaaaaaaa unsigned int b 0; for (int i 0; i 16; i) b | (1u (2 * i 1)); // 奇数位置 1 printf(%#x\n, b); // 0xaaaaaaaa return 0; }循环左移#include stdio.h unsigned int rol(unsigned int x, int n) { n % 32; if (n 0) return x; return (x n) | (x (32 - n)); } unsigned int ror(unsigned int x, int n) { n % 32; if (n 0) return x; return (x n) | (x (32 - n)); } int main(void) { unsigned int a 0x80000001; printf(%#x\n, rol(a, 1)); // 0x00000003 printf(%#x\n, ror(a, 1)); // 0xc0000000 return 0; }打印32位二进制#include stdio.h void printBin(unsigned int n) { for (int i 31; i 0; --i) putchar(((n i) 1u) ? 1 : 0); putchar(\n); } int main(void) { printBin(0x55); return 0; }异或交换两数#include stdio.h void swapXor(int *a, int *b) { if (a b) return; // 同一地址不能异或交换 *a ^ *b; *b ^ *a; *a ^ *b; } int main(void) { int a 10, b 12; swapXor(a, b); printf(%d %d\n, a, b); return 0; }
RELATED

相关推荐

建筑物立面缺陷识别数据集 AI立面裂缝数据集 墙面缺陷识别数据集 YOLO数据集

建筑物立面缺陷识别数据集 AI立面裂缝数据集 墙面缺陷识别数据集 YOLO数据集

外墙裂缝目标检测数据集项目详情任务类型目标检测图片总量6200张分类数量1类标注格式YOLO txt划分比例训练集:验证集:测试集 数据集简介 该数据集为建筑外墙裂缝目标检测数据集,采集自各类建筑物外墙实拍画面。数据集仅包含裂缝单一类别&…

📅 2026/10/24 2:30:47
2026 年的 AI 办公工具已经从“会写文案的对话框”走向“能在真实桌面环境中执行任务的智能体”

2026 年的 AI 办公工具已经从“会写文案的对话框”走向“能在真实桌面环境中执行任务的智能体”

2026 年的 AI 办公工具已经从“会写文案的对话框”走向“能在真实桌面环境中执行任务的智能体”。办公智能体可以读取文件、操作软件、调用浏览器、生成报告,并通过多轮规划完成任务闭环。 对开发者而言,Python 仍然是构建这类办公自动化能力的重要底座&…

📅 2026/10/24 2:30:47
DeepInfer 产品分析:DeepSeek 把自家“推理引擎“开源了,到底强在哪?

DeepInfer 产品分析:DeepSeek 把自家“推理引擎“开源了,到底强在哪?

DeepInfer 产品分析:DeepSeek 把自家"推理引擎"开源了,到底强在哪?一句话概括:DeepInfer 是 DeepSeek V4.1 Flash 背后那台发动机。它开源的不是一个玩具 demo,而是每天跑 155 万亿 token的生产级推理框架—…

📅 2026/10/24 2:25:47
MORE NEWS

更多资讯

📰

V4L2应用层编程实战:从open到STREAMON的完整流程与踩坑汇总

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

MATLAB轻量级病虫害识别系统:离线部署、INT8量化与田间决策闭环

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Windows NTP时间同步实战:w32time调优与ntpdate高精度校时方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

PMIC与MCU协同:利用PCA9422和PIC18F66K40实现低功耗电源管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

dom4j实战指南:Java中XML增删改查与常见坑全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

PHP反序列化调试实战:用Xdebug精准定位类型丢失问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬