# 结构体

C语言中的结构体是一种构造数据类型,它可以存储不同类型的数据项,这些数据项可以是基本数据类型,也可以是构造数据类型,甚至可以是结构体类型。

示例

#include <stdio.h>

struct MyStruct
{
    int a;
    char b;
    float c;
};

int main(){

    struct MyStruct s1 = {1, 'a', 1.1};
    struct MyStruct s2 = {2, 'b', 2.2};

    printf("s1.a = %d\n", s1.a);
    printf("s1.b = %c\n", s1.b);
    printf("s1.c = %f\n", s1.c);

    printf("s2.a = %d\n", s2.a);
    printf("s2.b = %c\n", s2.b);
    printf("s2.c = %f\n", s2.c);

    return 0;

}

# 结构体的定义和初始化

定义结构体变量的方式:

  • struct 结构体类型名 变量名;
  • struct 结构体类型名 变量名 = {成员1的初始值, 成员2的初始值, ...};
  • 直接定义结构体变量的成员(无需结构体类型名)

示例:

#include <stdio.h>

// `struct 结构体类型名 变量名;`

struct MyStruct1
{

    int a;
    char b;
    float c;

}; 
struct MyStruct1 s0; 

// `struct 结构体类型名 变量名 = {成员1的初始值, 成员2的初始值, ...};`

struct MyStruct2
{

    int a;
    char b;
    float c;

} s1 = {1, 'a', 1.1}; 

// 直接定义结构体变量的成员(无需结构体类型名)
struct
{

    int a;
    char b;
    float c;

} s2 = {2, 'b', 2.2}; 

结构体类型和结构体变量关系

  • 结构体类型:指定一个结构体的类型,可以定义多个结构体变量。没有具体数据,只是一个模板。系统也不分配内存。
  • 结构体变量:根据结构体类型定义的变量,有具体的数据,系统会分配内存。

结构体类型定义的方式

  • struct 结构体类型名 {成员列表};
  • typedef struct 结构体类型名 {成员列表} 结构体类型别名;

示例:

#include <stdio.h>

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

struct MyStruct1
{

    int a;
    char b;
    float c;

};

// `typedef struct 结构体类型名 {成员列表} 结构体类型别名;`

typedef struct MyStruct2
{

    int a;
    char b;
    float c;

} MyStruct2;

int main(){

    struct MyStruct1 s1 = {1, 'a', 1.1};
    MyStruct2 s2 = {2, 'b', 2.2};

    printf("s1.a = %d\n", s1.a);
    printf("s1.b = %c\n", s1.b);
    printf("s1.c = %f\n", s1.c);

    printf("s2.a = %d\n", s2.a);
    printf("s2.b = %c\n", s2.b);
    printf("s2.c = %f\n", s2.c);

    return 0;

}

# 结构体成员的使用


#include <stdio.h>
#include <string.h>

// 结构体的定义
struct Student
{

    char name[20];
    int age;
    float score;

};

int main(){

    // 结构体变量的定义
    struct Student s1 = {"张三", 18, 100};
    struct Student s2 = {"李四", 19, 90};

    // 结构体变量的使用
    printf("s1.name = %s\n", s1.name);
    printf("s1.age = %d\n", s1.age);
    printf("s1.score = %f\n", s1.score);

    printf("s2.name = %s\n", s2.name);
    printf("s2.age = %d\n", s2.age);
    printf("s2.score = %f\n", s2.score);

    // 结构体变量的赋值
    strcpy(s2.name, "王五");
    s2.age = 20;
    s2.score = 80;

    // 如果是指针变量
    strcpy(&s2->name, "王五");
    &s2->age = 20;

    printf("s2.name = %s\n", s2.name);
    printf("s2.age = %d\n", s2.age);
    printf("s2.score = %f\n", s2.score);

    return 0;

}

# 结构体数组

  #include <stdio.h>
  #include <string.h>

  // 结构体的定义
  struct Student
  {

      char name[20];
      int age;
      float score;

  }; 

  int main(){

      // 结构体数组的定义
      struct Student arr[3] = {
          {"张三", 18, 100},
          {"李四", 19, 90},
          {"王五", 20, 80}
      };

      // 结构体数组的使用
      for (int i = 0; i < 3; i++)
      {
          printf("arr[%d].name = %s\n", i, arr[i].name);
          printf("arr[%d].age = %d\n", i, arr[i].age);
          printf("arr[%d].score = %f\n", i, arr[i].score);
      }

      // 结构体数组的赋值
      strcpy(arr[2].name, "赵六");
      arr[2].age = 21;
      arr[2].score = 70;

      printf("arr[2].name = %s\n", arr[2].name);
      printf("arr[2].age = %d\n", arr[2].age);
      printf("arr[2].score = %f\n", arr[2].score);

      return 0;

  }

# 结构体互相嵌套

  #include <stdio.h>
  #include <string.h>

  // 结构体的定义

  struct Student
  {

      char name[20];
      int age;
      float score;

  };

  struct Teacher
  {

      int id;
      char name[20];
      int age;
      struct Student stu;

  };

  int main(){

      // 结构体变量的定义
      struct Teacher t1 = {1, "张三", 30, {"李四", 18, 100}};

      // 结构体变量的使用
      printf("t1.id = %d\n", t1.id);
      printf("t1.name = %s\n", t1.name);
      printf("t1.age = %d\n", t1.age);
      printf("t1.stu.name = %s\n", t1.stu.name);
      printf("t1.stu.age = %d\n", t1.stu.age);
      printf("t1.stu.score = %f\n", t1.stu.score);

      // 结构体变量的赋值
      strcpy(t1.stu.name, "王五");
      t1.stu.age = 20;
      t1.stu.score = 80;

      printf("t1.stu.name = %s\n", t1.stu.name);
      printf("t1.stu.age = %d\n", t1.stu.age);
      printf("t1.stu.score = %f\n", t1.stu.score);

      return 0;

  }

# 结构体赋值

结构体变量之间可以相互赋值,但是不能相互比较大小

  #include <stdio.h>
  #include <string.h>

  // 结构体的定义
  struct Student
  {

      char name[20];
      int age;
      float score;

  };

  int main(){

      // 结构体变量的定义
      struct Student s1 = {"张三", 18, 100};
      struct Student s2;

      // 结构体变量的赋值
      s2 = s1;

      // 结构体变量的使用
      printf("s2.name = %s\n", s2.name);
      printf("s2.age = %d\n", s2.age);
      printf("s2.score = %f\n", s2.score);

      return 0;

  }

# 结构体指针

# 指向普通结构体变量的指针

#include <stdio.h>
#include <string.h>

// 结构体类型的定义
struct Student
{

    char name[20];
    int age;
    float score;

};

int main(){

    // 结构体变量的定义
    struct Student s1 = {"张三", 18, 100};

    // 结构体指针的定义
    struct Student *p = &s1;

    // 结构体指针的使用
    printf("s1.name = %s\n", s1.name);
    printf("s1.age = %d\n", s1.age);
    printf("s1.score = %f\n", s1.score);

    printf("p->name = %s\n", p->name);
    printf("p->age = %d\n", p->age);
    printf("p->score = %f\n", p->score);

    printf("(*p).name = %s\n", (*p).name);
    printf("(*p).age = %d\n", (*p).age);
    printf("(*p).score = %f\n", (*p).score);

    return 0;

}

# 堆区结构体变量

  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>

  // 结构体类型的定义

  struct Student
  {

      char name[20];
      int age;
      float score;

  };

  int main(){

      // 结构体指针的定义
      struct Student *p = malloc(sizeof(struct Student));

      // 结构体指针的使用
      strcpy(p->name, "张三");
      p->age = 18;
      p->score = 100;

      printf("p->name = %s\n", p->name);
      printf("p->age = %d\n", p->age);
      printf("p->score = %f\n", p->score);

      return 0;

  }

# 结构体套一级指针

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 结构体类型的定义
struct Student
{

    char *name[20];
    int age;
    float score;

};

int main(){

    // 结构体指针的定义
    struct Student *p = malloc(sizeof(struct Student));

    // 结构体指针的使用
    strcpy(p->name, "张三");
    p->age = 18;
    p->score = 100;

    printf("p->name = %s\n", p->name);
    printf("p->age = %d\n", p->age);
    printf("p->score = %f\n", p->score);

    return 0;

}

# 结构体做函数参数

# 结构体普通变量做函数参数


#include <stdio.h>
#include <string.h>

// 结构体类型的定义
struct Student
{

    char name[20];
    int age;
    float score;

};

// 结构体变量做函数参数

void printStudent(struct Student s){

    printf("s.name = %s\n", s.name);
    printf("s.age = %d\n", s.age);
    printf("s.score = %f\n", s.score);

}

int main(){

    // 结构体变量的定义
    struct Student s1 = {"张三", 18, 100};

    // 结构体变量做函数参数
    printStudent(s1);

    return 0;

}

# 结构体指针做函数参数


#include <stdio.h>
#include <string.h>

// 结构体类型的定义

struct Student
{

    char name[20];
    int age;
    float score;

};

// 结构体指针做函数参数

void printStudent(struct Student *p){

    printf("p->name = %s\n", p->name);
    printf("p->age = %d\n", p->age);
    printf("p->score = %f\n", p->score);

}

int main(){

    // 结构体变量的定义
    struct Student s1 = {"张三", 18, 100};

    // 结构体指针做函数参数
    printStudent(&s1);

    return 0;

}

# 结构体数组做函数参数


#include <stdio.h>
#include <string.h>

// 结构体类型的定义

struct Student
{

    char name[20];
    int age;
    float score;

};

// 结构体数组做函数参数

void printStudent(struct Student arr[], int len){

    for (int i = 0; i < len; i++)
    {
        printf("arr[%d].name = %s\n", i, arr[i].name);
        printf("arr[%d].age = %d\n", i, arr[i].age);
        printf("arr[%d].score = %f\n", i, arr[i].score);
    }

}

int main(){

    // 结构体数组的定义
    struct Student arr[3] = {
        {"张三", 18, 100},
        {"李四", 19, 90},
        {"王五", 20, 80}
    };

    // 结构体数组做函数参数
    printStudent(arr, 3);

    return 0;

}

# 结构体指针数组做函数参数


#include <stdio.h>
#include <string.h>

// 结构体类型的定义

struct Student
{

    char name[20];
    int age;
    float score;

};

// 结构体指针数组做函数参数

void printStudent(struct Student *arr[], int len){

    for (int i = 0; i < len; i++)
    {
        printf("arr[%d]->name = %s\n", i, arr[i]->name);
        printf("arr[%d]->age = %d\n", i, arr[i]->age);
        printf("arr[%d]->score = %f\n", i, arr[i]->score);
    }

}

int main(){

    // 结构体数组的定义
    struct Student s1 = {"张三", 18, 100};
    struct Student s2 = {"李四", 19, 90};
    struct Student s3 = {"王五", 20, 80};

    struct Student *arr[3] = {&s1, &s2, &s3};

    // 结构体指针数组做函数参数
    printStudent(arr, 3);

    return 0;

}

# const 修饰结构体指针做函数参数


#include <stdio.h>
#include <string.h>

// 结构体类型的定义

struct Student
{

    char name[20];
    int age;
    float score;

};

// 结构体指针做函数参数

void printStudent(const struct Student *p){

    printf("p->name = %s\n", p->name);
    printf("p->age = %d\n", p->age);
    printf("p->score = %f\n", p->score);
    p->age = 20; // error

}

int main(){

    // 结构体变量的定义
    struct Student s1 = {"张三", 18, 100};

    // 结构体指针做函数参数
    printStudent(&s1);

    return 0;

}

# 共用体(联合体)

  • 共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。
  • 可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值,共用体提供了一种使用相同的内存位置的有效方式。
  • 共用体占用的内存应足够存储共用体中最大的成员。
  • 共用体的声明和结构体类似,但是必须使用union关键字。
  • 共用体的初始化和结构体类似,但是只能初始化第一个成员。
  • 共用体的成员地址和其他成员地址相同,共用体的成员地址和共用体变量地址相同。

示例:

#include <stdio.h>

union MyUnion
{

    int a;
    char b;
    float c;

};

int main(){

    union MyUnion u1 = {1};

    printf("u1.a = %d\n", u1.a);
    printf("u1.b = %c\n", u1.b);
    printf("u1.c = %f\n", u1.c);

    //所有成员的地址都是一样的
    printf("&u1.a = %p\n", &u1.a);

    return 0;

}

# 枚举

  • 枚举是一种用户自定义的数据类型,用于定义变量,可以将变量的值一一列举出来。
  • 枚举的每个值都可以叫做枚举的一个成员,每个成员都可以赋予一个值,如果没有赋值,系统会默认赋值。
  • 枚举的定义和结构体类似,但是必须使用enum关键字。
  • 枚举值是常量,不能在程序中用赋值语句再对它赋值
  • 枚举值的默认值从0开始,依次加1,如果前面一个成员赋值,后面没有赋值的成员会在前一个成员的基础上加1。

示例:

#include <stdio.h>

enum Season
{

    spring,
    summer,
    autumn,
    winter

};

int main(){

    enum Season s1 = spring;
    enum Season s2 = summer;
    enum Season s3 = autumn;
    enum Season s4 = winter;

    printf("s1 = %d\n", s1);
    printf("s2 = %d\n", s2);
    printf("s3 = %d\n", s3);
    printf("s4 = %d\n", s4);

    return 0;

}

# typedef

typedef 是C语言中的一个关键字,用来为类型取一个新的名字,可以使用 typedefint 取一个新的名字叫 myInt ,这样以后就可以用 myInt 来定义变量了。

  • typedef的作用是为一种数据类型定义一个新的名字,可以使用这个新的名字来定义变量。
  • typedef的语法:typedef 数据类型 新名字;
  • typedef的本质是给数据类型起一个别名,本质上是一个宏定义。
  • typedef仅限于为数据类型定义别名,不能为变量定义别名。

示例:


#include <stdio.h>

typedef int myInt;

int main(){

    myInt a = 10;
    printf("a = %d\n", a);

    return 0;

}