zoukankan      html  css  js  c++  java
  • C语言基础(19)-结构体,联合体,枚举和typedef

    一.结构体

    1.1 结构体struct定义及初始化

    #include <stdio.h> // 这个头文件在系统目录下
    #include <stdlib.h> // 使用了system函数
    #include <Windows.h>
    
    // 结构体简单使用
    void structUseDemo(void);
    // 输出student结构体的内容
    void print_student(struct student st);
    
    // 说明一种结构体类型
    struct student {
    
        char name[20];                        // << 姓名
        int age;                              // << 年龄
        int sex;                              // << 性别
        int class_id;                         // << 班级ID
    
    };
    
    
    int main() {
    
        structUseDemo();
        
        system("pause");
        return 0;
    
    }
    
    
    
    void structUseDemo(void) {
    
        // 定义结构体变量后赋值
        struct student st1;
        strcpy(st1.name,"张三");
        st1.age = 20;
        st1.sex = 1;  // 0代表男,1代表女
        st1.class_id = 1010;
    
        print_student(st1);
        
        printf("------------------------------------
    ");
    
        // 定义一个结构体变量,同时初始化它的内容
        struct student st2 = {"奥巴马",60,3,1010};
        print_student(st2);
    
        printf("------------------------------------
    ");
    
        struct student st3 = {"希拉里"}; // 只初始化第一个成员,后面都是0
        print_student(st3);
    
        printf("------------------------------------
    ");
        struct student st4 = {0}; // 所有成员都初始化为0
        print_student(st4);
    
        printf("------------------------------------
    ");
        struct student st5 = {.sex = 1,.name = "马英九"};
        print_student(st5);
    
    }
    
    
    
    void print_student(struct student st){
    
        printf("name=%s
    ", st.name);
        printf("age=%d
    ", st.age);
    
        if (st.sex == 0) {
            printf("sex=%s
    ", "");
        }
        else {
            printf("sex=%s
    ", "");
        }
    
        printf("class_id=%d
    ",st.class_id);
    
    }

    执行结果:

    1.2 结构体的内存对齐

    编译器在编译一个结构的时候总是采用内存对齐模式,结构体总是以最大的成员作为对齐单位,以偶数位对齐。

    如果结构体的所有成员都是同一种类型,那么这个结构体在内存和数组的存放方式是一样的。

    #include <stdio.h> // 这个头文件在系统目录下
    #include <stdlib.h> // 使用了system函数
    #include <Windows.h>
    
    // 结构体的简单使用1
    void structUseDemo1();
    
    // 结构体当中的所有成员在内存当中都是连续存放的
    struct A {
    
        int a1;
        int a2;
    
    };
    
    
    struct B {
    
        char a2; // 结构体成员是要对齐的
        int a1;
        
    };
    
    
    struct C{
    
        char a1;
        char a2;
        int a3;
    
    };
    
    
    struct D{
    
        char a1;
        int a3;
        char a2;
        
    };
    
    
    struct F {
    
        char a1;
        short a2;
        char a3;
        int a4;
    
    };
    
    struct H {
    
        char a1;
        short a2;
        int a3;
        short a4;
        char a5;
    
    };
    
    
    
    
    int main() {
    
        structUseDemo1();
        
        system("pause");
        return 0;
    
    }
    
    
    
    void structUseDemo1(){
    
        struct A a = {1,2}; // 定义并且初始化
        int *p = (int *)&a;
    
        printf("%u
    ",sizeof(a)); // 输出结果为8
        printf("%d
    ",*p);
        printf("%d
    ",p[1]);
    
        printf("----------- struct B -------------
    ");
    
        struct B b = {1,2};
        printf("%u
    ",sizeof(b)); // 输出结果为8
    
        printf("------------- struct C -----------
    ");
        struct C c = { 0 };
        printf("%u
    ",sizeof(c));
    
    
        printf("------------ struct D ------------
    ");
        struct D d = {0};
        printf("%u
    ",sizeof(d)); // 输出结果为12 !!!:因此struct C的写法比struct D的写法更合理
    
    
        printf("------------ struct F ------------
    ");
        struct F f = {1,2,3,4};
        printf("%p
    ",&f);
    
        printf("%u
    ",sizeof(f)); // 输出结果为12,结构体的对齐总是以偶数位进行对齐
    
    }

    执行结果:

    内存对齐示意图:

    1.3 指定结构体元素的位字段

    定义一个结构体的时候可以指定具体元素的位长

        struct test{
            char a : 2;//指定元素为2位长,不是2个字节长
        };

    1.4 结构体数组

    可以使用下列两种形式来定义结构体数组

    void structArrayUseDemo() {
    
        struct student st[3]; // 定义一个结构体变量数组
        strcpy(st[0].name,"张三");
        st[0].age = 50;
        st[0].sex = 0;
        st[0].class_id = 1;
    
    
        strcpy(st[1].name, "李四");
        st[1].age = 60;
        st[1].sex = 0;
        st[1].class_id = 2;
    
    
        strcpy(st[2].name, "王五");
        st[2].age = 70;
        st[2].sex = 0;
        st[2].class_id = 3;
    
        for (int i = 0; i < 3; i++) {
            print_student(st[i]);
            printf("--------------------------------
    ");
        };
    }
    
    
    void sturctArrayUseDemo1(){
    
        //struct student st[5] = { 0 }; // 将所有成员都置为0
        struct student st[5] = { { "张三", 30, 0, 90,0}, { "李四", 40, 1, 89,1 }, { "王五", 60, 1, 23,1}, { "赵六", 55, 0, 81 ,0}, { "陈七", 35, 0, 100,1} };
        for (int i = 0; i < 5; i++) {
            print_student(st[i]);
            printf("--------------------------------
    ");
        };
    
    }

    1.5 结构体嵌套结构体,结构体赋值及结构体指针

    例1:结构体嵌套结构体赋值:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    #pragma warning(disable:4996)
    
    

      struct B {

        int a1;
        struct A a2; // 这个结构体的成员是另一个结构体

      };

      struct C {

        int a1;
        struct B a2;

      };

    static void structUseDemo();
    
    static void structUseDemo() {
    
    
        struct B b;
        b.a1 = 10;
        b.a2.a1 = 0;
    
        struct C c;
        c.a2.a2.a1 = 0;
    
        printf("%u
    ",sizeof(struct B));
    
    }

    例2:结构体变量赋值

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    #pragma warning(disable:4996)
    
    static void structUseDemo1();
    
    // 结构体变量赋值
    static void structUseDemo1() {
    
        struct man m1 = {"圣堂刺客",20};
        struct man m2 = m1;
        printf("m1=%s
    ",m1.name);
        printf("m2=%s
    ", m2.name);
    
        struct man *p = &m1;
        //(*p).age = 100;
        //strcpy((*p).name,"风暴之灵");
    
        p->age = 100;
        strcpy(p->name,"风暴之灵");
        printf("m1.name=%s
    ",m1.name);
        printf("m1.age=%d
    ", m1.age);
    
    }

    例3:结构体指针

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    #pragma warning(disable:4996)
    
    static void structUseDemo2();
    
    static void structUseDemo2() {
    
        struct man m[10] = {0};
        struct man *p = &m; // p指向了数组m的首元素地址
        p[0].age = 1;
        strcpy(p[0].name,"帕克");
        p++;
        p->age = 100;
        strcpy(p->name,"莉娜");
        p++;
        p->age = 20;
        strcpy(p->name, "露娜");
        p = m; // 将指针归位
        /*for (int i = 0; i < 10;i++) {
            printf("name=%s,age=%d
    ",m[i].name,m[i].age);
        }*/
        for (int i = 0; i < 10;i++) {
            printf("name=%s,age=%d
    ",p->name,p->age);
            p++;
        }
    }

    1.6 在堆中创建结构体

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #pragma warning(disable:4996)
    
    void structUseDemo4(void);
    
    void structUseDemo4(void) {
    
        struct women *p = calloc(1, sizeof(struct women));
        p->name = calloc(100,sizeof(char));
        strcpy(p->name,"漩涡鸣人");
        p->age = 30;
    
        printf("当前p的名称为:%s,年龄为:%d
    ",p->name,p->age);
    
        free(p->name); // 一定要先翻译p->name,如果先释放p,会导致内存泄露
        free(p);
    
    }

    运行结果:

    1.7 结构体作为函数的参数

    下面有两个方法用于打印结构体成员变量的值

    // 结构体作为函数的参数
    void structUseDemo5(struct man m) {
        //在栈中会有类似这样的代码m = a;
    
        printf("%s,%d
    ",m.name,m.age);
    
    }
    
    // 1.不要把结构体作为函数的参数传递进去,因为这涉及到形参的拷贝,推荐传递结构体的指针
    // 2.由于传递的是结构体的地址,const可以保护实参的值不被修改
    void structUseDemo6(const struct man *m) {
    
        printf("%s,%d
    ",m->name,m->age);
    
    }

    二.联合体

    联合union是一个能在同一个存储空间存储不同类型数据的类型。

    联合体所占的内存长度等于其最长成员的长度,也有叫做共用体。

    联合体虽然可以有多个成员,但同一时间只能存放其中一种。

    联合体变量的任何一个成员赋值,都会影响到其它成员。

    三.枚举

    enum mysex { man = 5, woman }; // 说明了一个枚举 ,可以为其指定一个默认值,man = 5,woman就是6,依此类推
    
    void enumUseDemo1(void) {
    
        struct man m;
        strcpy(m.name,"佐助");
        m.age = 30;
        m.sex = man;
    
        printf("%d
    ",man);
    
    }
    
    // 输出为5.

    四.typedef

    typedef是一种高级数据特性,可以用于定义一个新的数据类型

    typedef unsigned char BYTE

    1#define不同,typedef仅限于数据类型,而不是能是表达式或具体的值。

    2typedef是编译器处理的,而不是预编译指令

    3typedef#define更灵活

    直接看typedef好像没什么用处,使用BYTE定义一个unsigned char。使用typedef可以增加程序的可移植性。

    typedef struct man M; // 说明了一个新的数据类型,名字叫M
    typedef unsigned char BYTE; // 说明了Byte这种数据类型
    typedef short NUM;
    
    void typedefUseDemo(void)
    {
        
        M m;
        m.age = 10;
        BYTE a;
    
    }
  • 相关阅读:
    双机信任关系
    VCS双机原理
    VCS常用指令
    TCL数组
    TCL数据类型
    TCL列表
    TCL基本语法
    CentOS防火墙中端口的开启和关闭
    会话保持技术及原理技术
    ESN
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6519635.html
Copyright © 2011-2022 走看看