嵌入式基础学习|C语言篇——结构体(含进阶)二

共用体:
union //联合--共用体 

在C语言中,共用体(Union)是一种特殊的数据类型,它允许不同类型的数据共享同一块内存空间,其主要特点和相关概念如下:

定义与语法

共用体使用union关键字来定义,语法形式为:
union 共用体名 {
    数据类型1 成员名1;
    数据类型2 成员名2;
    // 可以有多个不同类型的成员
    数据类型n 成员名n;
};
例如:
union Data {
    int i;
    float f;
    char c;
};
内存占用

共用体的大小取决于其最大成员的大小。在上述union Data的例子中,如果int类型占4个字节,float类型也占4个字节,char类型占1个字节,那么union Data占用的内存空间为4个字节,因为它要保证能容纳下最大的成员int或float。

成员访问

共用体可以通过成员名来访问其成员,但在某一时刻只能有一个成员的值是有效的。比如:
union Data data;
data.i = 10;
// 此时data.i的值是有效的,data.f和data.c的值是不确定的
data.f = 3.14;
// 此时data.f的值是有效的,data.i和data.c的值被覆盖
使用场景

• 节省内存:当程序需要处理不同类型的数据,但这些数据不会同时使用时,使用共用体可以节省内存空间。

• 数据解析:在网络通信或文件格式解析中,可能会接收到不同类型的数据,但它们在内存中的存储格式是特定的,这时可以使用共用体来方便地解析数据。

⭐️与结构体的区别

结构体的所有成员都有自己独立的内存空间,整个结构体的大小是所有成员大小之和(考虑内存对齐)。而共用体的所有成员共享同一块内存空间,大小取决于最大成员。

早期的时候,计算机的硬件资源有限,
能不能让多个成员变量 公用同一块空间 


//使用方式 类似 结构体  --- 也是构造类型 

struct 结构体名
{
  成员变量名
};


union 共用体名
{
  成员变量名
}; //表示构造了一个共用体类型 


//定义变量
//定义指针 
//定义数组 
//做函数形参 
//做函数返回值类型 


注意:
  1.共用体类型的大小 = 最大的成员的大小
  2.共用体初始化,只能写一个值,这个值是给第一个成员变量的值 
  3.共用体成员的访问方式 和 结构体一样
  4.共用体因为公用同一块空间
    赋值时,后赋值的会影响前面赋值的结果
  5.用途 
    a.节省空间 
    
    校园人员管理系统 
    struct student 
    {
       char name[20];
       int sno;
       float score;
    };
    
    struct teacher 
    {
       char name[20];
       int  tno;
       float salary;
    };
    
    
    struct member
    {
       char name[20];
       int  no;
       union 
       { 
          float salary;
          float score;
       }data;
    };
    
    struct member s;
    printf("score = %f\n",s.data.score);
    struct member t;
    printf("score = %f\n",s.data.salary);
    
    b.数据转换 
    192.168.0.59 //ip地址 --- 网络环境中 ---实际对应是一个32位的数值 
    
    
    #include <stdio.h>
    union Ip
    {
        unsigned char ip[4];
        unsigned int iip;
    };

    int main(int argc, const char *argv[])
    {
        union Ip d = {192,168,0,59};
        
        printf("ip = %#x\n",d.iip);
        
        return 0;
    }
------------------------------------------
枚举:

在C语言中,枚举(Enumeration)是一种用户自定义的数据类型,用于将一组相关的常量用符号名称来表示,方便程序的编写和维护。以下是关于枚举的主要概念:

定义与语法

枚举使用enum关键字来定义,基本语法形式为:
enum 枚举名 {
    枚举常量1,
    枚举常量2,
    // 可以有多个枚举常量
    枚举常量n
};
例如,定义一个表示星期的枚举类型:
enum Weekday {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
};
枚举常量的值

默认情况下,枚举常量会自动被赋予从0开始的整数值,如上述MONDAY的值为0,TUESDAY的值为1,以此类推。也可以手动指定枚举常量的值,例如:
enum Weekday {
    MONDAY = 1,
    TUESDAY = 2,
    // 其他常量按顺序依次递增
    SUNDAY = 7
};
枚举变量的定义和使用

可以像使用其他基本数据类型一样定义枚举变量,例如:
enum Weekday today;
today = MONDAY;
然后可以在程序中根据枚举变量的值进行相应的操作,比如:
if (today == MONDAY) {
    // 执行周一的相关操作
}
使用场景

• 提高代码可读性:用有意义的枚举常量名代替数字常量,使代码更易理解,如用MONDAY代替0来表示星期一。

• 限定取值范围:在函数参数或变量定义中使用枚举类型,可以限定其取值只能是枚举中定义的常量,有助于进行数据检查和错误处理。

• 状态标识:用于表示程序中的各种状态,如表示文件操作的状态,可以定义一个枚举来表示打开成功、打开失败、读取成功等状态。

   练习:
        学会从键盘输入 1到7 打印对应的星期 (英文)

 


如果一个变量只有几种可能的值,则可以定义为枚举类型。
所谓"枚举"是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

枚举 --- 提高代码可读性 


魔数 
幻数 

枚举 --- 将变量的可能值(常量值) 一一列举出来 
         将有关联的常量值,一一列举出来,组合成一个枚举类型 
         
enum 枚举名
{
   枚举值   
   //sun,mon,tue,wed,thu,fri,sat
};  
 //构造了一个枚举类型 
 
注意:
  1.枚举类型 本质是 用int型数据表示的 
    枚举类型 设计的不严谨的地方 
   
  
  
  
练习:
    歌曲的状态 

    PLAYING   1 
    PAUSE     2
    STOP      3
------------------------

typedef //type define 
     表示给已有类型起别名 
     
     
struct stu
{
};

struct stu s;

union demo
{
};
union demo d;

typedef struct stu s;  //s是struct stu 这个类型的别名 

s s1; //定义了一个 struct stu的变量 

 

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

void (*signal(int signum, void (*handler)(int) ))(int) ;


typedef int array_t[4];  //一维数组

array_t b[3]; //array_t => int[4]

 

位运算:
  指的是二进制位上的运算 

用途:
  嵌入式 --- 位运算 非常普遍 
  操作硬件 
  
c语言位运算:
  &    与 
  |    或 
  ^    异或
  ~    取反  
  <<   左移 
  >>   右移
  
  
  & 与 
    运算规则: 一假则假 
  | 或
    运算规则: 一真则真  
  ^ 异或
    运算规则: 相同为0 不同为1  
  << 左移  a<<n 
    运算规则: 将 左操作数a 左移 n位 
    左移一位 相当于 结果乘以2
       
    
int a = 0x55;

a & 0x33 

    
    0101 0101  //0x55
   &0011 0011  //0x33
----------------------
    0001 0001  //0x11
    
    
    0101 0101  //0x55
  | 0011 0011  //0x33
----------------------
    0111 0111 //0x77
    

    0101 0101  //0x55
  ^ 0011 0011  //0x33
----------------------
    0110 0110  //0x66
    
 
    ~ 0101 0101  //0x55
      1010 1010  //0Xaa
  
 
嵌入式:
   
   unsigned char reg = 0xff;
   
  7654|3210
     
  与 清0
  或 置1

    7654|3210
    1111 1111
  &         0
  -------------
  
  reg & 0xfe 
  
  
  int a;
  
  将a中的所有偶数位 清0
  
  int a = 0x1;
   
  
    7654|3210
    0000 0001  //1
    0000 0010  //2
    0000 0100  //4
    0000 1000  //8
    
    
    将a中的第5位 清0
    
    ~(1<<5)
    
    0010 0000
    1101 1111 & a 

        ~(1<<5|1<<8|1<<11)
        
练习:

  int a = 0xffffffff;
  将a中的所有偶数位 清0
  
练习:
  int a = 0;
   将a中的所有奇数位 置1 
    
   1010 
      
    
    7654|3210
    0000 0001  //1
    0000 0010  //2
    0000 0100  //4
    0000 1000  //8
    
    
    1000 0000 
    1100 0000 0 
右移:
    要看 要移动的数据的类型 
    看是有符号  --- 最高位补符号位   //算术右移  
        无符号     --- 最高位补0        //逻辑右移 
        
练习:
    考题: 计算 一个int 类型中有多少个1

    int a = 12134;
    
    1100 0001 
  &         1
------------------
    0000 0001
    
【练习】 
编写程序实现循环左移

 i<<2;
 
   1000 0000 

 step1:从最高位移出一位 
       是0还是1 
 step2:将最高位的 这个 0 或者 1 
       塞到尾部 
 step3:左移几位 
       循环走几遍 
        
1101 1111 1111 1111 1111 1111 1111 1111
 d
1011 1111 1111 1111 1111 1111 1111 1111
 b 
------------------------------------------------

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值