结构与联合体

在C++中,结构体(struct)和联合体(union)是两种用于组织数据的复合数据类型。它们允许我们将不同类型的变量组合在一起,从而更有效地管理数据。

结构体(struct)

结构体是由用户自定义的,允许存储不同类型数据的一种数据类型。它允许我们将相关的数据封装在一个单一的复合数据类型中。

定义结构体的语法如下:

struct 结构体类型名称 {
  数据类型1 成员变量名1;
  数据类型2 成员变量名2;
  ...
};

需要注意的是,结构体定义的末尾有一个分号 ;,别漏掉了。

例如,我们要存储一位同学的学号、姓名和年龄,可以像下面这样定义:

struct Student {
  int id; // 学号
  string name; // 姓名
  int age; // 年龄
  char gender; // 性别
};

现在有了一个名为 Student 的结构体类型,我们就可以通过下面的方式来创建和使用结构体:

struct Student stu1; // 定义学生1
stu1.id = 202310001;
stu1.name = "Jordan";
stu1.age = 23;
stu1.gender = 'Male';

下面是完整的代码:

#include <iostream>
using namespace std;

// 结构体类型声明
struct Student {
  int id; // 学号
  string name; // 姓名
  int age; // 年龄
  char gender; // 性别
};

int main() {
  struct Student s1; // 定义学生对象1
  s1.id = 202310001;
  s1.name = "Jordan";
  s1.age = 23;
  s1.gender = 'M';
  
  struct Student s2; // 定义学生对象2
  s2.id = 202310002;
  s2.name = "Alice";
  s2.age = 26;
  s2.gender = 'F';
  
  cout << "学生1: " << s1.name << " " << s1.age << " " << s1.gender << endl;
  cout << "学生2: " << s2.name << " " << s2.age << " " << s2.gender << endl;
  
  return 0;
}

运行程序,结果如下:

学生1: Jordan 23 M 学生2: Alice 26 F

上面是先定义结构体(Student),再单独创建具体的对象(s1s2);也可以直接紧跟在结构体的类型声明之后创建对象,代码如下所示:

// 结构体类型声明与创建
struct Student {
  int id; // 学号
  string name; // 姓名
  int age; // 年龄
  char gender; // 性别
}s1, s2, s[100];

上面代码在声明结构体类型的同时,创建了三个具体的结构体对象:

  • s1,学生对象1
  • s2,学生对象2
  • s[100],含有 100 个 Student 对象的数组 s

对于结构体类型的数组,访问方式与普通的数组差不多,只是通过数组直接拿到的数组元素是结构体,还需要多一层结构的成员变量访问。

下面是一个简单的示例,演示了结构体数组的访问。

#include <iostream>
using namespace std;

struct Student {
  int id; // 学号
  string name; // 姓名
  int age; // 年龄
  char gender; // 性别
} s[100];

int main() {
  int n;
  cin >> n;
  // 生成 n 个 Student 并赋值
  for (int i = 0; i < n; i++) {
    s[i].id = i + 1;
    s[i].name = "name" + to_string(i + 1);
    s[i].age = 10;
    if (i % 2 == 0) s[i].gender = 'M';
    else s[i].gender = 'F';
  }
  
  for (int i = 0; i < n; i++) {
    cout << s[i].id << " " << s[i].name << " " << s[i].age <<  " " << s[i].gender << endl;
  }
  
  return 0;
}

当输入 n=5n = 5 时,程序运行结果如下:

1 name1 10 M 2 name2 10 F 3 name3 10 M 4 name4 10 F 5 name5 10 M

结构体指针

我们也可以使用结构体指针来访问结构体的元素,有下面两种方式定义结构体指针。

定义结构体指针

你可以用一个结构体对象的地址来创建一个指针变量(也就是结构体指针变量)。

Student s;
s.id = 1;
s.name = "Jordan";
s.age = 23;
s.gender = 'M';

Student* p = &s; // 定义了一个指向 Student 结构的指针

使用指针访问结构体成员

通过指针可以访问结构体的成员,有两种常见的方式:

  1. 通过解引用操作符(*) 访问

通过解引用操作符*,我们可以访问指针所指向的结构体实例,并使用点操作符.访问其成员:

Student* p = &s; // 定义了一个指向 Student 结构的指针

cout << "Id: " << (*p).id << ", Name: " << (*p).name << endl;
  1. 通过箭头操作符(->)访问

C++提供了一种更简便的方式,即使用箭头操作符 -> 来访问成员,它结合了解引用和访问成员的操作:

Student* p = &s; // 定义了一个指向 Student 结构的指针

cout << "Id: " << p->id << ", Name: " << p->name << endl;

联合体(union)

联合体也是一种将多个不同类型的数据组合在一起的用户定义的数据类型,但与结构体不同的是,联合体的所有成员共享相同的内存空间。这意味着在同一时间只能有一个成员占用存储空间。

定义联合体的语法如下:

union Data {
    int intValue;
    float floatValue;
    char charValue;
};

我们可以通过以下方式创建和使用联合体:

Data data;
data.intValue = 10;
cout << data.intValue << endl;

data.floatValue = 3.14;
cout << data.floatValue << endl;

下面是一个完整的示例,展示了如何定义和使用联合体:

#include <iostream>
using namespace std;

union Data {
    int intValue;
    float floatValue;
    char charValue;
};

int main() {
    Data data;
    data.intValue = 10;
    cout << "Integer: " << data.intValue << endl;

    data.floatValue = 3.14;
    cout << "Float: " << data.floatValue << endl;

    data.charValue = 'A';
    cout << "Char: " << data.charValue << endl;

    return 0;
}

结构体与联合体看起来很相似,但它们在内存使用和应用场景上有着显著的不同。

  • 内存分配:结构体的每个成员都有自己独立的内存空间,而联合体的所有成员共享同一块内存。
  • 使用场景:结构体适合用于需要同时存储和访问多个不同类型的数据的情况;联合体适合用于节省内存的场景,尤其是在同一时间只需要一个数据成员的情况下。

练习

【待补充】

小结

通过理解和掌握结构体和联合体,我们可以在C++编程中更有效地组织和管理数据。