自定义类型:联合体和枚举

简介: 联合体类型,联合体的大小计算,联合体的实际应用,练习:判断大小端,枚举类型,枚举类型的声明:枚举类型的优点,枚举类型的实际案例:

联合体类型

联合体的声明:

union 联合体名{

成员列表

}变量列表;

注意事项:

1、联合体所有成员共⽤同⼀块内存空间,它们的地址也相同

#include <stdio.h>
union Un
{
 char c;
 int i;
};
int main()
{
 union Un un = {0};
 printf("%p\n", &(un.i));
 printf("%p\n", &(un.c));
 printf("%p\n", &un);
 return 0;
}

2、给联合体其中一个成员赋值,其他成员的值也跟着变化

#include <stdio.h>
union Un
{
 char c;
 int i;
};
int main()
{
 union Un un = {0};
 un.i = 0x11223344;
 un.c = 0x55;
 printf("%x\n", un.i);
 return 0;
}


un.i在存中的变化:


当我们对un.c赋值0x55的时候,un.i的值发生了改变:


联合体的大小计算

计算规则:

联合体大小的计算规则与结构体大小的计算规则(内存对齐)有相似之处

1、联合的⼤⼩⾄少是最⼤成员的⼤⼩

2、联合体最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍

#include <stdio.h>
union Un1
{
 char c[5]; //5字节        1  8  1
 int i;     //4字节        4  8  4
};0
union Un2
{
 short c[7];//14字节       2  8  2
 int i;     //4字节        4  8  4
}; 
int main()
{
 printf("%d\n", sizeof(union Un1));
 printf("%d\n", sizeof(union Un2));
 return 0;
}

①Un1中最大成员大小为5,最大对齐数为4,所以联合体大小为8

②Un2中最大成员大小为14,最大对齐数为4,所以联合体大小为16


联合体的实际应用

       我们要搞⼀个活动,要上线⼀些礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息

图书:书名、作者、⻚数

杯⼦:设计

衬衫:设计、可选颜⾊、可选尺⼨

可以直接写出⼀下结构:

struct gift_list
{
//公共属性
int stock_number;//库存量
double price; //定价
int item_type;//商品类型
//特殊属性
char title[20];//书名
char author[20];//作者
int num_pages;//⻚数
char design[30];//设计
int colors;//颜⾊
int sizes;//尺⼨
};

  上述的结构其实设计的很简单,⽤起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样使得结构体的⼤⼩偏⼤,浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息是常⽤的。⽐如:商品是图书,就不需要design、colors、sizes这些属性。 所以我们应当把公共属性单独写出来,剩余的属于各种商品本⾝的特殊属性放进联合体中:


/

#include <stdio.h>
struct gift_list
{ //通用属性
  int stock_number;//库存量
  double price;//定价
  int item_type;//商品类型
  //特殊属性
  union {
    struct
    {
      char title[20];//书名
      char author[20];//作者
      int num_pages;//页数
    }books;
    struct
    {
      char design[30];//设计
    }mug;
    struct {
      char design[30];//设计
      int colors;//颜色
      int sizes;//尺寸
    }shirt;
  }items;
};
int main()
{
  struct gift_list gl = {0};
  gl.stock_number = 100;
  gl.price = 25;
  gl.item_type = 2;
  gl.items.books = {"wode","nde",30};
  printf("%s,%s,%d", gl.items.books.title, gl.items.books.author, gl.items.books.num_pages);
  return 0;
}


练习:判断大小端

#include <stdio.h>
int check()
{
  int a = 1;
  return (*(char*)&a);
}
int main()
{
  int a = 1;
  if (check)
    printf("小端\n");
  else
    printf("大端\n");
  return 0;
}

利用联合体实现大小端的判断:

#include <stdio.h>
int check_sys()
{
  union
  {
    int i;
    char c;
  }un;
  un.i = 1;
  return un.c;
}
int main()
{
  if (check_sys() == 1)
    printf("小端\n");
  else
    printf("大端\n");
  return 0;
}


   当我们给un.i赋值给1后,小端机器在内存中的存储形式为01  00  00  00,然后此时联合体内的char c也要占用一个字节的空间覆盖了原来01所在的内存空间,此时返回un.c所在的内存空间发现原来的01变为现在的00,所以为小端机器。  

枚举类型

       枚举就是一一列举,它可以用来列举我们日常生活中常见的各种东西,比如性别里的男和女,颜色里的赤橙黄绿青蓝紫......

枚举类型的声明:

enum 类型名
{
枚举常量 (建议全部大写)
};
enum Sex//性别
{
 MALE,
 FEMALE,
 SECRET
};
enum Color//颜⾊
{
 RED,
 GREEN,
 BLUE
};

其中,enum Color和enum Sex叫做枚举类型,MALE、FEMALE等叫做枚举常量它们是枚举类型的可能取值我们打印一下它们看看:

#include <stdio.h>
enum Sex//性别
{
  MALE,
  FEMALE,
  SECRET
};
enum Color//颜⾊
{
  RED,
  GREEN,
  BLUE
};
int main()
{
  enum Sex sex = MALE;  //枚举类型的使用方式就是将枚举常量赋值给枚举类型的变量;
  printf("%d %d %d ", MALE, FEMALE, SECRET);
  return 0;
}


我们会发现打印结果为0 1 2,这是以为这些枚举常量都是有值的,默认从0开始,依次递增1,当然在声明枚举类型的时候也可以赋初值。

枚举类型的优点

1、增加代码的可读性和可维护性


2、和#define定义的标识符⽐较枚举有类型检查,更加严谨。


3、便于调试,预处理阶段会删除 #define 定义的符号


4、使⽤⽅便,⼀次可以定义多个常量


5、枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤

枚举类型的实际案例:

本案例取自本人的另一篇文:《贪吃蛇---C语言版本》

//贪吃蛇游戏中反应蛇移动方向的枚举类型
enum DIRECTION
{
    UP,            //向上
    DOWN,          //向下 
    LEFT,          //向左
    RIGHT          //向右
};
//定义反应游戏状态的枚举类型
enum GAME_STATUS
{
    OK,              //游戏正常运⾏
    KILL_BY_WALL,    //撞墙
    KILL_BY_SELF,    //自己撞到自己
    END_NOMAL        //正常结束(自己选择ESC结束游戏)
};
//利用switc判断ps->_Dir的不同方向
  switch (ps->_Dir)
  {
  case UP:
    //如果蛇是向上运动的,那么蛇运动的下一个结点的x轴坐标与蛇头保持一致,y轴坐标为蛇头y轴坐标减一,下面的就不一一写解释了
    pNext->x = ps->_pSnake->x;
    pNext->y = ps->_pSnake->y - 1;
    break;
  case DOWN:
    pNext->x = ps->_pSnake->x;
    pNext->y = ps->_pSnake->y + 1;
    break;
  case LEFT:
    pNext->x = ps->_pSnake->x - 2;
    pNext->y = ps->_pSnake->y;
    break;
  case RIGHT:
    pNext->x = ps->_pSnake->x + 2;
    pNext->y = ps->_pSnake->y;
    break;
  }

  与switch结合是目前我所见到的唯一一个对于枚举类型的使用案例,可能还会有其他的后续学习过程中会进行适当的补充......

相关文章
|
2月前
|
存储 编译器 C语言
自定义类型(二)结构体位段,联合体,枚举
本文介绍了C++中结构体的默认对齐数修改,位段的声明和使用,联合体的概念及其实际应用,以及枚举类型的用途。通过实例展示了如何优化内存使用和提高代码可读性。
21 1
|
7月前
|
存储 编译器 Linux
自定义类型——结构体、联合体、枚举
自定义类型——结构体、联合体、枚举
|
6月前
|
存储 算法
枚举类型和联合体类型
枚举类型和联合体类型
29 0
|
7月前
|
编译器
联合体和枚举
联合体和枚举
39 0
|
C语言
C语言知识点:结构体,枚举,联合体
C语言知识点:结构体,枚举,联合体
77 0
|
7月前
|
编译器 测试技术 C语言
详解自定义类型:枚举与联合体!
详解自定义类型:枚举与联合体!
|
7月前
|
存储 开发框架 .NET
自定义类型:联合体和枚举类型(联合体与结构体的区别)
自定义类型:联合体和枚举类型(联合体与结构体的区别)
|
编译器
自定义类型联合体(上)
自定义类型联合体
49 0
自定义类型联合体(上)
|
存储 编译器
自定义类型联合体(下)
自定义类型联合体
39 0
自定义类型联合体(下)
自定义类型枚举(上)
自定义类型枚举
37 0