九、结构体共用体枚举

本文详细介绍了C语言中的结构体、结构体变量、结构体数组、结构体指针、共用体和枚举的概念、定义、初始化及应用。通过实例展示了如何操作结构体数据,并给出了结构体大小计算的规则。此外,还讨论了枚举类型及其在程序中的使用。内容深入浅出,适合C语言初学者和进阶者阅读。
摘要由CSDN通过智能技术生成

【1】结构体

1.概念:

由用户自定义的一种构造类型,用于描述一个复杂事物,表示多种不同类型数据的集合。

2.定义格式:

​ struct 结构体名
​ {
​ 数据类型 成员1;
​ 数据类型 成员2;
​ …
​ 数据类型 成员n;
​ };

3.结构体类型大小
1)字节对齐原则

​ 选取结构体成员中最大的类型跟value(4字节)比较,按字节数小的为标准开辟空间。

2)节省空间原则

​ 在保证数据不被破坏的前提下,尽可能向上压缩空间。

3)特殊情况:

四字节内部对齐原则

 struct num
	 {
	     char a;
		 short b;  //4
		 char c;   //4
		 int d;    //4
	 }; 		

​ sizeof(struct num) = 12

【2】结构体变量

1.概念:

通过结构体类型定义的变量称为结构体变量。

2.定义方式:

​ [存储类型] [结构体类型] 变量名;

1)先定义结构体,再通过结构体类型定义结构体变量。
     struct phone
      {
         int id;         //编号
         char brand[10]; //品牌
         char mod[20];   //型号
         char cpu[20];   //处理器
         float price;    //价格
      };
      struct phone ph1;              

2)定义结构体的同时定义结构体变量。
	  struct phone
      {
         int id;         //编号
         char brand[10]; //品牌
         char mod[20];   //型号
         char cpu[20];   //处理器
         float price;    //价格
      }ph2,ph3;     

3)缺省结构体类型名定义结构体变量。
	  struct 
      {
         int id;         //编号
         char brand[10]; //品牌
         char mod[20];   //型号
         char cpu[20];   //处理器
         float price;    //价格
      }ph1,ph2,ph3;	 

//注: 1.缺省结构体名定义变量时,只能在定义结构体的同时将所需变量定义好,
​ 后续无法再通过struct 结构体名去定义结构体变量了。
​ 2.一般用于结构体嵌套时,通常省略内层的结构体名。

3.结构体变量初始化
1)先定义结构体,再通过结构体类型定义结构体变量,定义变量的同时进行初始化。
  struct phone
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  };

struct phone ph1 = {1001,“华为”,“P50 Pocket”,“骁龙888 4G”,10988};

2)定义结构体的同时定义结构体变量,同时对结构体变量进行初始化。
 struct phone
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  }ph2,ph3;  
3)定义结构体变量时未初始化,后面再逐个成员赋值。

通过结构体变量名访问成员的形式:
通过 . 进行访问 : 结构体变量名.成员

  struct phone
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  }ph3;

  ph3.id = 1003;
  strcpy(ph3.brand,"Apple");
  strcpy(ph3.mod,"iPhone13 pro max");
  strcpy(ph3.cpu,"A15");
  ph3.price = 998;              

4.给结构体类型起别名

typedef 原类型名 自定义名;

  typedef struct 
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  }PH;	  
  PH ph1;

  typedef struct 
  {
    char name[5]; 
    int  id;
    struct
    {
        float Chinese;
        float Math;           
        float English;
    }s;
  }STU;
  STU student_1;
  strcpy(student_1.name,"陈剑");
  student_1.id = 2003101;
  student_1.s.Chinese = 60.5;

作业1:计算结构体大小(文档)
作业2:预习结构体数组。
从终端录入手机信息,写一个函数,该函数参数是结构体数组,
按照手机价格从低到高顺序输出手机信息。

【3】结构体数组

1.概念:

用于存放结构体变量的数组,结构体数组中存放的元素都是结构体类型的。

2.定义方式:
1)先定义结构体类型,再通过结构体类型定义结构体数组。
      struct phone
      {
         int id;         //编号
         char brand[10]; //品牌
         char mod[20];   //型号
         char cpu[20];   //处理器
         float price;    //价格
      };

​ struct phone ph_arr2[5];

2)定义结构体的同时定义结构体数组。
  struct phone
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  }ph_arr[5];
3.结构体数组初始化
1)先定义结构体类型,再通过结构体类型定义结构体数组,同时对结构体数组进行初始化。

struct phone ph_arr2[5] = {{1001,“华为”,“P50”,“骁龙888”,10499},{1001,“华为”,“P50”,“骁龙888”,10499}};

2)定义结构体的同时定义结构体数组,同时对结构体数组进行初始化。
  struct phone
  {
     int id;         //编号
     char brand[10]; //品牌
     char mod[20];   //型号
     char cpu[20];   //处理器
     float price;    //价格
  }ph_arr[5] = {
      {1001,"华为","P50","骁龙888",10499},
      {1001,"华为","P50","骁龙888",10499}
  };                                          

3)定5义结构体数组时未初始化,之后再对数组中的元素成员分别赋值。
  ph_arr[0].id = 1002;
  strcpy(ph_arr[0].brand,"小米");
4.结构体数组的输入输出
  struct phone ph_arr[5] = {0};
  scanf("%d",&ph_arr[0].id);
  通过循环进行优化:
  for(int i=0;i<5;i++)
  {
      scanf("%d %s %s %s %f",&ph_arr[i].id,ph_arr[i].brand,ph_arr[i].mod,ph_arr[i].cpu,&ph_arr[i].price);
  }

【4】结构体指针

1. 概念:

指向结构体变量的指针称为结构体指针

2.定义格式:

​ struct 结构体名 *结构体指针名;
​ 应用:

	  struct phone
      {
         int id;         //编号
         char brand[10]; //品牌
         char mod[20];   //型号
         char cpu[20];   //处理器
         float price;    //价格
      }ph_arr[5];
	  struct phone *p = ph_arr;
	访问形式:
	  (*p).id = 1001;
	    p->id = 1001;


练习:打印功能选项,由用户进行功能选择,
​ 例如:输入1,进行手机信息录入。
​ 输入2,进行手机信息打印。
​ 输入6,退出系统。

【5】共用体
1. 概念:

不同数据类型的数据使用共同的存储区域,这种数据构造类型称为共用体,又称联合体。

2. 定义格式:

​ union 共用体名
​ {
​ 成员列表;
​ };
​ 例如:

  union data
    	 {
    	   char  cval;
    	   int   ival;
    	   float fval;
    	 };
3.共用体类型变量定义:
(1)先定义共用体类型,后定义变量。

    union data
    	 {
    	   char  cval;
    	   int   ival;
    	   float fval;
    	 };
    	 union data a,b,c;
(2)定义共用体类型的同时定义变量。

    union data
    	 {
    	   char  cval;
    	   int   ival;
    	   float fval;
    	 }a,b,c;
    	 如果不再定义新的变量,也可以将共用体的名字省略:
    	 union
    	 {
    	   char  cval;
    	   int   ival;
    	   float fval;
    	 }a,b,c;
4.共用体大小计算:

​ 结构体占用内存大于等于所有成员占用内存的总和,因为成员之间可能存在空隙,而共用体占用的内存空间,等于最大的成员变量占用的内存。
​ 共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,会覆盖掉原有的成员数据。
​ 比如 :共用体data里占用内存最大的是int类型数据,占用4个字节,那么共用体data占用的内存大小为4。

      
union test
{
  char s[20];
  int b;
  double c;
}a;
sizeof(a) = 20;

通过共用体验证大小端:
#include<stdio.h>
union test
{
  char a;
  int b;
}num;                                   
int main(int argc, const char *argv[])
{
    num.b = 0x12345678;
    printf("%#x\n",num.a);

​    return 0;
}

【5】枚举:

1.定义:

只能取预先定义值的数据类型是枚举类型。

2.格式:

enum 枚举类型名
{
枚举元素列表
};
例如: 列出一个星期有几天:
enum week
{
Mon, Tues, Wed, Thurs, Fri, Sat, Sun
};
可以看到,我们仅仅给出了名字,却没有给出名字对应的值,
因为枚举值默认从0开始,往后逐个加1,也就是说,week 中的 Mon、Tues … Sun
对应的值分别为 0、1 … 6。

​ 我们也可以给每个名字都指定一个值:

   enum week
		  { 
		    Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 
		  };
		  由于枚举类型值逐个递增1,我们也可以只给第一个名字指定一个值:
		  enum week
		  { 
		    Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun 
		  };

说明: 1)枚举类型是一种类型,通过它可以定义枚举变量
enum week a,b,c;
2)可以将列表里的值赋给枚举变量
enum week a = Mon, b = Web, c = Sat;
3)枚举列表中的Mon、Tues、Wed这些标识符的作用范围是全局的(严格来说是 main() 函数内部)
不能再定义与他们名字相同的变量。
4)Mon、Tues、Wed等都是常量,不能再次赋值,只能将他们赋给其他变量。
示例:判断用户输入的是星期几。

#include <stdio.h>
		 int main(){
		 enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } day;
		 scanf("%d", &day);
		 switch(day){
			case Mon: puts("Monday"); break;
			case Tues: puts("Tuesday"); break;
			case Wed: puts("Wednesday"); break;
			case Thurs: puts("Thursday"); break;
			case Fri: puts("Friday"); break;
			case Sat: puts("Saturday"); break;
			case Sun: puts("Sunday"); break;
			default: puts("Error!");
		  }	
		  return 0;
		}		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值