C语言学习——结构体_联合体_枚举用法直通

简介: C语言学习——结构体_联合体_枚举用法直通

一、结构体嵌套


#include <stdio.h>
// 出生日期:年月日
struct sBirthday
{
  int iYear;
  int iMonth;
  int iDay;
};
// 公民信息
struct sSCitizenIDInfo
{
  char cName[10];
  char cSex[4];
  sBirthday  BirthDate;  // 结构体变量作为另一个结构体的成员
  char cAddress[100];
};
int main()
{
  struct sSCitizenIDInfo sInfo = { "王中华", "女", { 2010, 12, 12 }, "北京市朝阳区" };
  struct sSCitizenIDInfo *pCID = &sInfo;
  printf("姓名:%s\n性别:%s\n出生日期:%d 年 %d 月%d 日\n地址:%s\n",pCID->cName,pCID->cSex,pCID->BirthDate.iYear,pCID->BirthDate.iMonth,pCID->BirthDate.iDay,pCID->cAddress);
  return 0;
}


结果为



二、结构体数组


所谓结构体数组,是指数组中的每个元素都是一个结构体。在实际应用中,C语言结构体数组常被用来表示一个拥有相同数据结构的群体,比如一个班的学生、一个车间的职工等。

// 公民信息
struct sSCitizenIDInfo
{
  char cName[10];
  char cSex[4];
  sBirthday  BirthDate;
  char cAddress[100];
}pCArr[3] = {
    { "王中华", "男", { 2010, 12, 12 }, "北京市朝阳区" },
    { "刘小小", "女", { 1990, 2, 22 }, "北京市东城区" },
    { "吴小莉", "女", { 2000, 9, 30 }, "北京市海淀区" }
};
#include <stdio.h>
// 出生日期:年月日
struct sBirthday{
  int iYear;
  int iMonth;
  int iDay;
};
// 公民信息
struct sSCitizenIDInfo{
  char cName[10];
  char cSex[4];
  sBirthday  BirthDate;
  char cAddress[100];
}pCArr[3] = { { "王中华", "男", { 2010, 12, 12 }, "北京市朝阳区" },
    { "刘小小", "女", { 1990, 2, 22 }, "北京市东城区" },
    { "吴小莉", "女", { 2000, 9, 30 }, "北京市海淀区" }
};
int main()
{
  struct sSCitizenIDInfo *pCID = pCArr;
  // 数组下标输出
  for (int i = 0; i < 3; i++)
  {
    printf("\n姓名:%s\n性别:%s\n出生日期:%d年%d月%d日\n地址:%s\n", pCArr[i].cName, pCArr[i].cSex, pCArr[i].BirthDate.iYear, pCArr[i].BirthDate.iMonth, pCArr[i].BirthDate.iDay, pCArr[i].cAddress);
  }
    // 结构指针变量输出
  printf("\n-----------------------------------------------------------------------------------\n");
  for (int i = 0; i < 3; i++)
  {
    printf("\n姓名:%s\n性别:%s\n出生日期:%d年%d月%d日\n地址:%s\n", (pCID[i]).cName, (pCID[i]).cSex, (pCID[i]).BirthDate.iYear, (pCID[i]).BirthDate.iMonth, (pCID[i]).BirthDate.iDay, (pCID[i]).cAddress);
  }
  return 0;
}


结果如下:




三、联合体


结构体(Struct):


是一种构造类型或复杂类型,可以包含多个类型不同的成员。


在C语言中,还有另外一种和结构体非常类似的语法,叫做共用体(union),它的定义格式为:


union 共用体名
{
    成员列表......
};


共用体有时也被称为联合或者联合体;


结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。


结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。


1、共用体也是一种自定义类型,可以通过它来创建变量:

union data
{
  int i;
  char ch;
  double d;
};
union data ud;


2、定义共用体的同时创建变量


union data
{
  int i;
  char ch;
  double d;
}ud;


3、如果不再定义新的变量,也可以将共用体的名字省略:


union
{
  int i;
  char ch;
  double d;
}ud,cd;


四、枚举


在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成本项工作:


如这样:

#define MONDAY    1
#define TUESDAY 2
#define WEDNESDAY 3
#define THURSDAY  4
#define FRIDAY  5
#define SATURDAY  6
#define SUNDAY  7





方法一:枚举类型的定义和变量的声明分开


enum DAY
{
      MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY yesterday;
enum DAY today;
enum DAY tomorrow; //变量tomorrow的类型为枚举型enum DAY
enum DAY good_day, bad_day; //变量good_day和bad_day的类型均为枚举型enum DAY


方法二:类型定义与变量声明同时进行:


enum //跟第一个定义不同的是,此处的标号DAY省略,这是允许的。
{
    saturday,
    sunday = 0,
    monday,
    tuesday,
    wednesday,
    thursday,
    friday
} workday; //变量workday的类型为枚举型enum DAY
enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days; //变量days的类型为枚举型enum week 
enum BOOLEAN { false, true } end_flag, match_flag; //定义枚举类型并声明了两个枚举型变量

方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明:


typedef enum workday
{
    saturday,
    sunday = 0,
    monday,
    tuesday,
    wednesday,
    thursday,
    friday
} workday; //此处的workday为枚举型enum workday的别名
workday today, tomorrow; //变量today和tomorrow的类型为枚举型workday,也即enum workday


五、C语言字节对齐


一、为什么要字节对齐  


  需要字节对齐的根本原因在于CPU访问数据的效率问题。


二、正确处理字节对齐  


  对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:  


  数 组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。


  联 合 :按其包含的长度最大的数据类型对齐。


  结构体: 结构体中每个数据类型都要对齐。


三、什么时候需要设置对齐


在设计不同CPU下的通信协议时,或者编写硬件驱动程序时寄存器的结构这两个地方都需要按一字节对齐。即使看起来本来就自然对齐的也要使其对齐,以免不同的编译器生成的代码不一样.


案例1


#pragma pack (4)
#include <stdio.h>
struct stu
{
  char sex;
  int length;
  char name[10];
};
struct stu my_stu;
int main()
{
  printf("占据:%d字节\n", sizeof(my_stu));
  return 0;
}


结果:



案例分析:


上面定义了对其字节数为4字节,char本身1字节,在这占四位,int四位,char[10]占10位,但最后两位直接算四位,4+4+12=20字节


案例2:


#include <stdio.h>
#pragma pack(1) //让编译器对这个结构作1字节对齐
struct test
{
  char x1;
  short x2;
  float x3;
  char x4;
  int a[3];
  double d;
}TT;
//#pragma pack() //取消1字节对齐,恢复为默认4字节对齐
int main()
{
  printf("char占据:%d字节\n", sizeof(char));
  printf("short占据:%d字节\n", sizeof(short));
  printf("float占据:%d字节\n", sizeof(float));
  printf("char占据:%d字节\n", sizeof(char));
  printf("a占据:%d字节\n", sizeof(TT.a));
  printf("d占据:%d字节\n", sizeof(TT.d));
  printf("\n共计占据:%d字节\n", sizeof(TT));
  return 0;
}


结果:



六、typedef





相关文章
|
25天前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
33 10
|
25天前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
29天前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
29天前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
1月前
|
编译器 C语言 C++
C语言结构体
C语言结构体
26 5
|
6月前
|
Ubuntu 编译器 Linux
C语言中经典的结构体和联合体共用实例
C语言中经典的结构体和联合体共用实例
59 0
|
存储 开发框架 .NET
【C语言】自定义类型:结构体,枚举,联合体
【C语言】自定义类型:结构体,枚举,联合体
61 0
【C语言】自定义类型:结构体,枚举,联合体
|
6月前
|
存储 C语言
C语言进阶⑮(自定义类型)(结构体+枚举+联合体)(结构体实现位段)(下)
C语言进阶⑮(自定义类型)(结构体+枚举+联合体)(结构体实现位段)
42 0
|
6月前
|
存储 编译器 程序员
C语言:自定义类型 - 结构体 & 联合体 & 枚举
C语言:自定义类型 - 结构体 & 联合体 & 枚举
47 2
|
6月前
|
存储 编译器 C语言
[C语言]自定义类型(结构体~枚举~联合体)
[C语言]自定义类型(结构体~枚举~联合体)