C语言

7. C语言--结构体

Posted on 2022-01-30,5 min read

7.结构体

7.1 结构体

类型的声明

7.1.1 介绍

结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员”,其描述了一块内存区间的大小及解释意义。

  • 结构体是一种数据类型,地位同等于int、float等
  • 结构体类型不是系统定义好的,由程序员自己定义
  • 使用struct关键字来标识定义的结构体类型
  • 结构体通常用来表示类型不同但又相关的若干数据
  • 关键字struct和结构体名组成类型标识符
  • 成员又称为成员变量,是结构体所包含的若干个基本的结构类型
  • 结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针

7.1.2 声明

// 格式:
struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list;

// tag: 结构体标签
// member-list: 变量定义
// variable-list: 结构体变量
// 一般情况下:tag、member-list、variable-list 3部分至少出现两个

// 使用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple;
// 可以用Simple作为类型声明新的结构体变量
// eg:
Simple s;

7.1.3 例

int main()
{
  struct Person
  {
    char name[10];
    short age;
  };

  struct Student
  {
    char id[20];
    struct Person p;
  };
  return 0;
}

7.2 结构体初始化

7.2.1 定义时初始化

int main()
{
  struct Person
  {
    char name[10];
    short age;
  };

  struct Student
  {
    char id[20];
    struct Person p;
  } s = {"1914121006", {"listen", 25}};
  return 0;
}

7.2.2 定义后初始化

struct Person
{
  char name[10];
  short age;
};

struct Student
{
  char id[20];
  struct Person p;
};

int main()
{
  struct Student s = { "1914121006", {"listen", 25} };
  return 0;
}

7.3 结构体成员访问

7.3.1 .

struct Person
{
  char name[10];
  short age;
};

struct Student
{
  char id[20];
  struct Person p;
};

int main()
{
  struct Student s = { "1914121006", {"listen", 25} };
  printf("id: %s\nname: %s\nage: %d\n", s.id, s.p.name, s.p.age);
  return 0;
}


7.3.2

struct Person
{
  char name[10];
  short age;
};

struct Student
{
  char id[20];
  struct Person p;
};

int main()
{
  struct Student s = { "1914121006", {"listen", 25} };
  struct Student* ps = &s;
  printf("id: %s\nname: %s\nage: %d\n", (*ps).id, (*ps).p.name, (*ps).p.age);
  printf("id: %s\nname: %s\nage: %d\n", ps->id, ps->p.name, ps->p.age);
  return 0;
}


7.4 结构体传参

struct Person
{
  char name[10];
  short age;
};

struct Student
{
  char id[20];
  struct Person p;
};

void print1(struct Student s)
{
  printf("id: %s\nname: %s\nage: %d\n", s.id, s.p.name, s.p.age);
}

void print2(struct Student* ps)
{
  printf("id: %s\nname: %s\nage: %d\n", ps->id, ps->p.name, ps->p.age);
}

int main()
{
  struct Student s = { "1914121006", {"listen", 25} };
  print1(s); // 值传递
  print2(&s); // 址传递
  return 0;
}


  • print1和pirnt2对比:
    • print1: 值传递,更安全。传参时,需要开辟一块与结构体变量s同等大小的区域用于将s复制一份到print1函数中,相比于print2消耗更多的内存资源。此外,print1函数中不可以修改结构体变量s中的值。
    • print2: 址传递。传参时,在32位平台使用4字节内存资源,在64位平台使用8字节。相比于print1,消耗更少的内存资源。此外,print2可以修改结构体变量s中成员变量的值。但print2相对于print1不安全。

函数传参的时候,参数是需要压栈的,并且按照参数列表的顺序,从右向左压栈。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

结论:结构体传参时,要传结构体的指针。


下一篇: 6. C语言--指针→