嵌入式 Day 17:结构体、共用体、枚举、typedef、位运算

一、结构体(struct 关键字)

结构体类型用于描述复杂数据,是一种构造类型(用户自定义类型)。

1. 结构体的声明

struct Student

{

  int id; 

  char name[20];

  float score;

};

说明:

  • struct 是关键字;

  • Student 是结构体名;

  • 成员列表可包含变量、数组、指针等;

  • 成员间用分号分隔;

  • 结尾必须加分号

2. 定义变量

struct Student s;

3. 成员赋值

s.id = 1;

strcpy(s.name, "zhangsan");

s.score = 99.5;

注意:

  • 使用点运算符 .

  • s.name = "zhangsan" 是错误的,不能直接赋值给数组。

4. 结构体变量之间赋值

struct Student s1 = {1, "zhangsan", 90};

struct Student s2;

s2 = s1;

5. 初始化结构体变量

struct Student s = {1, "zhangsan", 99};

也可以使用部分初始化(C99支持):

struct Student s = { .id = 1, .score = 90 };

未赋值成员自动补 0。


二、结构体内存对齐原则

结构体内存对齐规则(32位系统为例):

  1. 默认按最大成员大小对齐;

  2. 每个成员的偏移量必须是其类型大小的整数倍;

  3. 总大小是最大对齐值的整数倍。

struct Demo {

           char a;

           int b;

           short c;

        };

sizeof(struct Demo) 输出为 12 字节。

内存对齐的目的是提高CPU访问效率(空间换时间)


三、结构体成员访问

1. 点操作符 . 用于变量

printf("%d\n", s.id);

2. 箭头操作符 -> 用于指针

struct Student *p = &s;

printf("%d\n", p->id);

3.输出函数1:注:该函数为值传递(过程需要拷贝);不建议使用

4.输出函数2:注:该函数为指针传参(效率更好)


四、结构体常见操作示例

遍历结构体数组

结构体逆序

交换结构体数组的元素

采用回调函数按学生成绩排序

采用qsort函数按学生名字排序


五、共用体(union

共用体多个成员共享同一块内存,总大小为最大成员的大小。

4个字节被3个长度不同的变量共享时,共享总是从起始部分开始共享的(所有成员起始地址是相同的);

定义示例

union Data {

          int i;

          float f;

          char ch;

        };

共用体只能使用最后一次赋值的成员。

union Data d;

d.i = 10;

d.f = 3.14; // 覆盖了 i 的值

共用相同的内存空间(所以称为共用体);  运行结果:4(共占4个字节)

六、使用共用体判断大小端


七、枚举类型(enum

用于限定变量的取值范围,提高可读性。

示例定义

enum Status {

            SLEEP, // 0

            RUNNING, // 1

            ERROR = 4,

            STOP // 5

        };

说明:

  • 默认从 0 开始;

  • 可以指定某个枚举常量的值;

  • 枚举本质是 int 类型;

  • 可用于 switch 语句。

使用示例

enum Status s = RUNNING;

printf("%d\n", s); // 输出 1

注意事项:

(1)枚举中逐个列举的值,默认是从0开始;如果有给定的值,则后续没有给值的枚举成员依次加1;

(2)枚举本质是一个int 类型的数据(可以放在switch中使用);

(3)每个值可以用%d输出。

示例:运行结果:sleep

运行结果为4;

运行结果为2(列举的值默认从0开始);

运行结果为13(有给定的值,后续没有给值的枚举常量依次+1);

八、typedef 关键字

用于给已有类型起别名,提升可读性,简化复杂声明。

示例

typedef int INT;

INT a = 10;

typedef struct {

              int id;

              char name[20];

          } Student; Student s;


九、位运算

1. 按位与 &

unsigned char a = 0x9E; // 1001 1110

unsigned char b = 0x32; // 0011 0010

printf("%02X\n", a & b); // 12

作用:清零特定位

2. 按位或 |

printf("%02X\n", a | b); // 0xBE

作用:指定位置1;

3. 按位异或 ^

printf("%02X\n", a ^ b); // 0xAC

作用:位翻转

4. 取反 ~

printf("%02X\n", (unsigned char)(~a)); // 0x61

作用:0变1,1变0

5. 左移 <<

1、<<:双目运算符,优先级为5级,结合方向自左至右;

2、写法:a<<n  (表示将a这个数据左移n位 )(C语言中为逻辑左移)

3、最高位无论是1还是0全丢掉,后面补0;

4、作用:指定位清零( ~(1 << n));

eg:

0000 0001 
0000 0010
左移1位  相当于乘 2  

6. 右移 >>

1、>>:双目运算符,优先级为5级,结合方向自左至右;

2、写法:a>>n(表示将 a这个数据 右移 n位)

3、算术右移是看符号位和看数据类型的:

(1)有符号数据类型,右移时,最高位补的是符号位; (算术右移)     

(2)无符号类型的数据,右移时,最高位补的0 ;(逻辑右移)

注:在使用右移运算符时最好定义无符号数据类型(eg:unsigned char)

1000

1100

-----------

0100

0010

右移1位  相当于除 2   


总结

本节内容是 C 语言和底层操作的重要基础,包括:

  • struct 建立复杂数据结构;

  • union 共用内存空间;

  • enum 提升代码可读性;

  • typedef 简化类型书写;

  • 位运算用于高效的位级操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值