C语言基础-结构体

结构体的现实意义

现实世界里有很多事物是由不同的部分组合起来的。例如手机由屏幕、CPU、芯片、电池等多个部分组成。同时,对于每个组件如电池又由其他细小组件组成。结构体就是把这些组件组合在一起,进行统一的访问和管理。
结构体可以理解成是对现实世界的抽象。结构体不仅可以记录不同类型的数据,而且使得数据结构是“高内聚,低耦合”,更加利于程序的阅读和理解及移植。而且结构体的存储方式可以提高CPU对内存的访问速度。

定义结构体

struct 数据类型名{
//结构体数据成员列表
};

实例1

struct student{
    char * name;
    char * gender;
    char * mail;
    int age;

};

在定义完结构体后,要声明结构体变量

  • 方式1
struct Student student;
  • 方式2
struct Student{
    char name[10];
    char * gender;
    char * mail;
    int age;

}stu;  // 在这里增加一个变量`stu`,则`stu`为结构体变量
  • 方式3
struct {
    char *name;
    char * gender;
    char * mail;
    int age;
}stu;

这种方式之后无法再继续定义变量。

结构体变量的初始化

  • 结构体定义时初始化
struct Student{
    char name[10];
    char * gender;
    char * mail;
    int age;
}student = {"张三", "男", "helloworld@qq.com", 21};
  • 变量定义时初始化
struct Student stu;
stu = (struct Student){
    "张三",
    "男",
    "helloworld@qq.com",
    21
};
  • 单成员进行赋值
//对数组类型的数据不能直接赋值,例如stu.name = "张三";
strcpy(stu.name, "张三");
stu.age = 21;
stu.gender = "男";

结构体变量的使用

可以使用变量.成员字段来使用结构体的数据成员

strcpy(stu.name, "张三");
stu.age = 21;
stu.gender = "男";
stu.mail = "helloworld@qq.com";
printf("%s\n", stu.name);
printf("%d\n", stu.age);
printf("%s\n", stu.gender);
printf("%s\n", stu.mail);

结构体数组

  • 语法定义
struct Student{
    char * name;
}stu[5];

使用上与单个结构体变量相同,在数组中需要加上在数组中的下标

  • 使用案例
# include <stdio.h>
# include <string.h>
struct Student{
    char * name;

};
int main(){
    struct Student stu[2];
    stu[0] = (struct Student){"张三"};
    printf("%s\n", stu[0].name);
    return 0;

}
  • 结构体指针

指向结构体类型的指针

  • 使用案例
# include <stdio.h>
# include <string.h>
struct Student{
    char * name;

};
int main(){
    struct Student stu = {"张三"};
    struct Student *p;
    p = &stu;
    printf("%s\n", (*p).name);
    printf("%s\n", p->name);
    return 0;
}

结构体嵌套

一个结构体当中可以包含其他类型的结构体,结构体自身当中不能包含相同类型的结构体,但是可以包含执行自身的指针

  • 使用案例
# include <stdio.h>
# include <string.h>
struct gender{
    char * ch;
};

struct Student{
    char * name;
    struct Student * s;
    struct gender gen;

};
int main(){
    struct gender gen = {"男"};
    struct Student stu = {"张三"};
    struct Student student = {
        "张三",
        & stu,
        gen
    };
    printf("%s\n",student.name);
    printf("%s\n",(student.s)->name);
    printf("%s\n",student.gen.ch);
    return 0;
}

结构体变量在作为参数传递的时候使用的是值传递

typedef struct 与struct的区别

typedef关键字可以将一种数据类型添加一种别名,例如typedef int Int,此时Int等价于int。在struct中,定义的别名可以直接用于定义变量,等价于struct类型名

  • 使用案例
# include<stdio.h>
# include <string.h>
struct gender {
    char * ch;
};

typedef struct Student{
    char *name;
    struct Student * s;
    struct gender gen;

}Stu;

int main(){
    struct gender gen = {"男"};
    struct Student stu = {"张三", NULL};
    struct Student student = {
        "张三",
        &stu,
        gen

};
// 使用新定义的类型名定义指针变量,等价于struct Student
     Stu *s = &student;
     printf("%s\n",(*s).name);
     printf("%s\n", ((*s).s)->name);
     printf("%s\n",(*s).gen.ch);
    return 0;
}

enum枚举

枚举就是将我们数据可能存在的结果有限个的罗列出来,比如一个人的性别不是男就是女。

  • 使用案例
# include <stdio.h>
# include <string.h>
enum Gender{
    MAN = 1, //不指定值则从0开始
    WOMAN = 2 //不指定值则从上一个定义的值开始递增,为2
};
int main(){
    //定义枚举变量
    enum Gender g;
    // 枚举变量只可能存在一种值
    g = WOMAN;
    printf("%d\n",g);
    return 0;
}

union共用体

共用体内部可以定义N个变量,但是这
N个变量之间会相互影响。共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员

  • 使用案例
# include <stdio.h>
# include <string.h>
union Data{
    int a;
    char b;
    short c;
};
int main(){
    union Data d;
    d.a = 46;
    printf("%d\n",d.a);
    printf("%c\n",d.b);
    printf("%d\n",d.c);
    printf("%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
    d.b = 'a';
    printf("%d\n",d.a);
    printf("%c\n",d.b);
    printf("%d\n",d.c);
    printf("%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
    d.c = 47;
    printf("%d\n",d.a);
    printf("%c\n",d.b);
    printf("%d\n",d.c);
    return 0;

}

结果显示:

46
.
46
%%%%%%%%%%%%%
97
a
97
%%%%%%%%%%%%%
47
/
47