结构体的定义

1. 简单结构体

  1. 声明结构体
  2. 初始化结构体
  3. 调用结构体的成员
#include <stdio.h>

// 声明一个结构体
struct student {
    int num;    // 结构体成员
    char name[20];
    char sex;
    int age;
    float score;
}; 

int main(void) {
	// 初始化结构体 struct student就可以理解为一个数据结构,如int、float等
    struct student s = {12, "libai", '0', 15, 100.0};
    // 通过 . 的方式,来获取结构体成员
    printf("%d %s %c %d %5.2f", s.num, s.name, s.sex, s.age, s.score);
    return 0;
}

2. 空结构体声明

struct EmptyStruct{

}

3. 匿名结构体

👀️ 匿名结构体没有类型,下面的代码中的 stu1stu2是变量名

struct {
    int id;
    char *name;
    int age;
    float score;
} stu1, stu2;

4. 结构体结合typedef

没有使用typedef关键字的结构体每次都需要加struct,会显得很麻烦,如下面的代码

struct Student {
    int id;
    char *name;
};
int main(){
    // 声明一个变量需要:数据类型 + 变量名,比如 int a, float b
    struct Student stu1;
    struct Student stu2;
}

使用了typedef就非常的方便

typedef struct Student {
  int id;
  char *name;
}Student;

👀️ 值得注意的是:后面的Student就表示类型了,而不是变量名。

而且我们还可以省略 struct 右边的Student

typdef struct {
  int id;
  char *name;
}Student;

5. 结构体的嵌套

typdef struct {
  int year;
  int month;
  int day;
}Birthday;

typdef struct {
  int id;
  char *name;
  Birthday birthday;
}Student;

结构体变量

1. 结构体变量的声明

声明结构体变量不需要内存。

声明结构体变量不需要内存。

  • 方式一
typdef struct {
  int id;
  char *name;
}Student;

int main(){
  Student s1,s2; // 声明2个学生变量,学生1和学生2
}
  • 方式二
typdef struct {
  int id;
  char *name;
}Student, s3;

👀️ 注意:我们可以在定义结构体的时候,可以声明结构体变量

Student表示类型,类型后面可以表示结构体变量了。

2. 结构体变量的赋值

结构体变量的赋值通过花括号的方式复制

如果结构体里面也有结构体,用花括弧嵌套即可。

typdef struct {
  int year;
  int month;
  int day;
}Birthday;

typdef struct {
  int id;
  char *name;
  Birthday birthday;
}Student;

int main(){
  Student s1 = {1,"xiaohua",{2024,1,2}};
}

3. 访问成员变量

使用 . 操作符

结构体指针

😕 stu1是结构体变量,存储了Tom的信息。

pstu,是结构体指针变量。且它指向了stu1变量

struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组
    float score;  //成绩
} stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
#include <stdio.h>

struct teacher{
    int age;
    char sex;
    char name[25];
};

int main(void) {
    struct teacher t = {18, 'm', "wangli"};
    struct teacher *p = &t;
    // 方式一:因为 . 的优先级比 * 高,所以要加括号
    printf("%d %c %s\n", (*p).age, (*p).sex, (*p).name);
    // 方式二:使用指针符号 ->
    printf("%d %c %s\n", p->age, p->sex, p->name);
    return 0;
}

  • 思考题?
#include <stdio.h>

struct teacher{
    int age;
    char sex;
    char name[25];
};

int main(void) {
    struct teacher t[3] = {18, 'm', "wangli", 19, 'f', "lisi"};
    struct teacher *p = t;
    int age;
    age = p->age++; // 1. age = p->age; 2. p->age++;
    printf("age=%d, p->age=%d\n", age, p->age);   // 18,19
    age = p++->age; // 1. aeg = p->age; 2. p++;
    printf("age=%d, p->age=%d\n", age, p->age);   // 19, 19

    return 0;
}

结构体数组

我们要知道如何声明结构体数组。int a[10]; 表示声明一个长度为10的数组a

// 注意 class是变量名,且他的类型是一个结构体数组
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组 
    float score;  //成绩
}class[5];
  • 结构体数组在定义的同时也可以初始化
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组 
    float score;  //成绩
}class[5] = {
    {"Li ping", 5, 18, 'C', 145.0},
    {"Zhang ping", 4, 19, 'A', 130.5},
    {"He fang", 1, 18, 'A', 148.5},
    {"Cheng ling", 2, 17, 'F', 139.0},
    {"Wang ming", 3, 17, 'B', 144.5}
};
  • 当对数组中全部元素赋值时,也可不给出数组长度
struct stu{
    char *name;  //姓名
    int num;  //学号
    int age;  //年龄
    char group;  //所在小组 
    float score;  //成绩
}class[] = {
    {"Li ping", 5, 18, 'C', 145.0},
    {"Zhang ping", 4, 19, 'A', 130.5},
    {"He fang", 1, 18, 'A', 148.5},
    {"Cheng ling", 2, 17, 'F', 139.0},
    {"Wang ming", 3, 17, 'B', 144.5}
};
#include <stdio.h>

// 声明一个结构体
struct student {
    char name[20]; // 结构体成员
    char sex;
    int age;
}; 

int main(void) {
    struct student s[3];
    int i = 0;
    for(i = 0; i < 3; i++) {
        scanf("%s %c%d", s[i].name, &s[i].sex, &s[i].age);
    }

    for(i = 0; i < 3; i++) {
        printf("%s %c %d\n", s[i].name, s[i].sex, s[i].age);
    }

    return 0;
}

结构体大小

在结构体中,为了提高CPU的访问效率,其内存是存在对齐的

struct teacher{
    int age;
    char sex;
    char name[5];
};

int main(void) {
	// 为什么是12?
    printf("%lu\n", sizeof(struct teacher));    // 12
    return 0;
}

C++引用

C++引用是一种内存地址别名,它允许我们使用一个名称来引用另一个变量。引用通常用作函数参数和返回值类型,以便可以避免复制大型数据结构。

在C++中,使用&符号来声明一个变量的引用。例如,以下代码定义了一个整数变量a,并为其创建了一个引用b:

int a = 5;
int &b = a;

这将创建一个名为b的引用,它指向变量a的内存地址。现在,如果我们修改b的值,实际上是在修改a的值,因为b和a共享同一块内存空间。例如

b = 10; // 现在 a 的值也变成了 10

注意,引用必须在定义的同时初始化,且不能被重新绑定到另一个对象。此外,引用可以被用作函数参数,以便可以在函数内部操作原始变量而不需要进行复制。

C++引用用于函数参数

引用通常被用作函数参数,以便可以在函数内部操作原始变量而不需要进行复制。通过引用传递参数比通过值传递参数更高效,因为它避免了在函数调用时的数据拷贝。

void increment(int& x) {
    x++;
}

这个函数接受一个整数的引用,并将其值增加1。现在,如果我们调用该函数并传递一个整数变量作为参数,该变量的值将被修改:

int a = 5;
increment(a); // 现在 a 的值变成了 6

请注意,当我们将引用作为参数传递给函数时,实际上是将原始变量的内存地址传递给了函数。因此,在函数内部对引用所引用的变量的任何修改都会影响到原始变量