【重要】C语言进阶 -- 自定义类型:结构体、枚举、联合

本章重点

结构体

  1. 结构体类型的声明
  2. 结构的自引用
  3. 结构体变量的定义和初始化
  4. 结构体内存对齐
  5. 结构体传参
  6. 结构体实现位段(位段的填充&可移植性)

枚举

  1. 枚举类型的定义
  2. 枚举的优点
  3. 枚举的使用

联合(共用体)

  1. 联合类型的定义
  2. 联合的特点
  3. 联合大小的计算

1.结构体

1.1 结构体类型的声明

结构的基础知识:结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量

#include <stdio.h>

// 声明一个结构体类型,名字叫stu
// 里面的内容叫做结构体成员变量
struct stu
{
    char name[20]; // 名字
    int age;       // 年龄
    char sex[5];   // 性别
    char id[20];   // 学号
}s3,s4,s5;                 // 分号不能少,s3,s4,s5为全局的结构体变量,与下面的声明相同
// 创建结构体变量,全局变量,在函数内部叫做局部变量
struct stu s1;
struct stu s2;

int main(){
    struct stu s6;  // 局部变量
    return 0;
}

特殊声明:不常用

// 匿名结构体
struct 
{
   int a;
   char b;
   float c;
}x; // 通过x.的方式进行调用结构体成员变量

1.2 结构体的自引用

struct  Node
{
    int date;
    struct Node *next;
};

1.3 结构体变量的定义和初始化

// 结构体变量重定义
typedef struct node
{
    int data;
} Node;

int main()
{
    struct node n1;  
    Node n2;
    return 0;
}
struct S{
    char c;
    int a;
    double d;
    char arr[];
};

struct S s = {'A',10,3.14,"world"};

1.4 结构体传参

结构体传参,采用传地址的方式,效率更高

函数传参的时候,参数是需要压栈的,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

#include <stdio.h>

struct S
{
    int a;
    char c;
    double d;
};

void init(struct S *temp)
{
    temp->a = 100;
    temp->c = 'a';
    temp->d = 3.14;
}

void print1(struct S temp)
{
    printf("%f\n", temp.d);
}

void print2(struct S *temp)
{
    printf("%f\n", temp->d);
}

int main()
{
    struct S s;
    init(&s);   // 给结构体传参
    print1(s);  // 调用结构体参数进行计算
    print2(&s); // 调用结构体参数进行计算,常用方法2
    return 0;
}

1.5 结构体位段

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是int、unsigned int 或 signed int,只要整型即可,char也是整型
  2. 位段的成员名后边有一个冒号和一个数字

位段:二进制位,位段用来节省空间

位段内存的分配:

  1. 位段的成员可以是int unsigned        int signed        int或者是char(属于整型家族)类型
  2. 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的‘
  3. 位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段
#include <stdio.h>

struct S
{
    int a : 2; // 给a  2个比特位
    int b : 5; // 给b 5个比特位
    int c : 10;
    int d : 30;
};
// 共47个bit位,换算成字节,6个字节即可满足 


int main()
{
    struct S s;
    printf("%d\n", sizeof(s)); // 8个字节
}

2 枚举

枚举顾名思义就是列举,把可能的取值进行列举。

枚举类型的定义:

enum Color
{
    RED,  // 默认为0,可以赋初始值,例RED = 1
    YELLOW, // 1
    BLUE   // 2
};
int main(){
    enum Color r = RED; // 赋其他值会报错
    return 0;
}

枚举的优点:可以使用#define定义常量,为什么非要使用枚举?

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符比较,枚举有类型检查,更加严谨
  3. 防止命名污染(封装)
  4. 便于调试
  5. 使用方便,一次可以定义多个常量

枚举的使用:

3 联合(共用体)

  • 联合类型的定义:联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
  • 联合的特点:共用同一块内存空间,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
// 联合类型的声明
union un
{
    char c;
    int i;
};

int main()
{
    union un u;
    printf("%d\n", sizeof(u));  //结果为4
    return 0;
}

联合大小的计算:

  • 联合的大小至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

猜你喜欢

转载自blog.csdn.net/qq_45355603/article/details/126201940